@@ -821,13 +821,34 @@ function with_source_path(f, path)
821821 end
822822end
823823
824- function ensure_setup! (ctx:: TestContext , ts:: TestSetup , logs:: Symbol )
824+ # Call `runtestsetup(ts, ...)` for each `ts::Testsetup` required by the given `TestItem`
825+ # Return setup_name => module_name pairs
826+ function runtestsetups (ti:: TestItem , ctx:: TestContext ; logs:: Symbol , force:: Bool = false )
827+ # Initialse with the list of _requested_ setups, so that if it no setup by that name was
828+ # found when including files we return the setup name as the module name. Attempting to
829+ # import that name, like `using $setup`, will then throw an appropriate error.
830+ setup_to_mod = Dict {Symbol,Symbol} (ti. setups .=> ti. setups)
831+ for (ts_name, ts) in ti. testsetups
832+ @debugv 1 " Ensuring setup for test item $(repr (ti. name)) $(ts_name)$(_on_worker ()) ."
833+ setup_to_mod[ts_name] = runtestsetup (ts, ctx; logs)
834+ end
835+ return setup_to_mod
836+ end
837+
838+ # Run the given `TestSetup`, add the resulting `Module` to the `TestContext` and returns the
839+ # name of the `Module` (i.e. returns a `Symbol`).
840+ # If the `TestSetup` has already been evaluated on this process and so is already in the
841+ # `TestContext`, simply returns the `Module` name.
842+ # Pass `force=true` to force the `TestSetup` to be re-evaluated, even if run before.
843+ function runtestsetup (ts:: TestSetup , ctx:: TestContext ; logs:: Symbol , force:: Bool = false )
825844 mods = ctx. setups_evaled
826845 @lock mods. lock begin
827- mod = get (mods. modules, ts. name, nothing )
828- if mod != = nothing
829- # we've eval-ed this module before, so just return the module name
830- return nameof (mod)
846+ if ! force
847+ mod = get (mods. modules, ts. name, nothing )
848+ if mod != = nothing
849+ # we've eval-ed this module before, so just return the module name
850+ return nameof (mod)
851+ end
831852 end
832853 # We haven't eval-ed this module before, so we need to eval it.
833854 # In case the setup fails to eval, we discard its logs -- we will attempt to eval
@@ -930,24 +951,16 @@ function runtestitem(
930951 prev = get (task_local_storage (), :__TESTITEM_ACTIVE__ , false )
931952 task_local_storage ()[:__TESTITEM_ACTIVE__ ] = true
932953 try
933- for (setup_name, ts) in ti. testsetups
934- # ensure setup has been evaled before
935- @debugv 1 " Ensuring setup for test item $(repr (name)) $(setup_name)$(_on_worker ()) ."
936- ts_mod = ensure_setup! (ctx, ts, logs)
937- # eval using in our @testitem module
938- @debugv 1 " Importing setup for test item $(repr (name)) $(setup_name)$(_on_worker ()) ."
954+ # eval `using $TestSetup` in our @testitem module.
955+ testsetups = runtestsetups (ti, ctx; logs)
956+ for (ts_name, ts_module_name) in testsetups
957+ @debugv 1 " Add setup imports for test item $(repr (name)) $(setup_name)$(_on_worker ()) ."
939958 # We look up the testsetups from Main (since tests are eval'd in their own
940959 # temporary anonymous module environment.)
941- push! (body. args, Expr (:using , Expr (:., :Main , ts_mod)))
942- # ts_mod is a gensym'd name so that setup modules don't clash
943- # so we set a const alias inside our @testitem module to make things work
944- push! (body. args, :(const $ setup_name = $ ts_mod))
945- end
946- for setup_name in setdiff (ti. setups, keys (ti. testsetups))
947- # if the setup was requested but is not in our testsetups, then it was never
948- # found when including files. We still add `using $setup` in the test item
949- # so that we throw an appropriate error when running the test item.
950- push! (body. args, Expr (:using , Expr (:., :Main , setup_name)))
960+ push! (body. args, Expr (:using , Expr (:., :Main , ts_module_name)))
961+ # ts_module_name is a gensym'd name so that setup modules don't clash,
962+ # so set a const alias inside our @testitem module to make things work.
963+ push! (body. args, :(const $ ts_name = $ ts_module_name))
951964 end
952965 @debugv 1 " Setup for test item $(repr (name)) done$(_on_worker ()) ."
953966
0 commit comments