@@ -785,14 +785,14 @@ function include_testfiles!(project_name, projectfile, paths, ti_filter::TestIte
785785 # we set it below in tls as __RE_TEST_SETUPS__ for each included file
786786 setup_channel = Channel {Pair{Symbol, TestSetup}} (Inf )
787787 setup_task = @spawn begin
788- setups = Dict {Symbol, TestSetup} ()
789- for (name, setup ) in setup_channel
790- if haskey (setups , name)
788+ testsetups = Dict {Symbol, TestSetup} ()
789+ for (name, ts ) in setup_channel
790+ if haskey (testsetups , name)
791791 @warn " Encountered duplicate @testsetup with name: `$name `. Replacing..."
792792 end
793- setups [name] = setup
793+ testsetups [name] = ts
794794 end
795- return setups
795+ return testsetups
796796 end
797797 hidden_re = r" \.\w "
798798 @sync for (root, d, files) in Base. walkdir (project_root)
@@ -844,21 +844,21 @@ function include_testfiles!(project_name, projectfile, paths, ti_filter::TestIte
844844 # prune empty directories/files
845845 close (setup_channel)
846846 prune! (root_node)
847- ti = TestItems (root_node)
848- flatten_testitems! (ti )
849- check_ids (ti . testitems)
850- setups = fetch (setup_task)
851- for (i, x ) in enumerate (ti . testitems)
847+ tis = TestItems (root_node)
848+ flatten_testitems! (tis )
849+ check_ids (tis . testitems)
850+ testsetups = fetch (setup_task)
851+ for (i, ti ) in enumerate (tis . testitems)
852852 # set a unique number for each testitem
853- x . number[] = i
853+ ti . number[] = i
854854 # populate testsetups for each testitem
855- for s in x . setups
856- if haskey (setups, s )
857- push! (x . testsetups, setups[s ])
855+ for setup_name in ti . setups
856+ if haskey (testsetups, setup_name )
857+ push! (ti . testsetups, setup_name => testsetups[setup_name ])
858858 end
859859 end
860860 end
861- return ti, setups # only returned for testing
861+ return tis, testsetups # only returned for testing
862862end
863863
864864function check_ids (testitems)
@@ -941,28 +941,18 @@ function with_source_path(f, path)
941941 end
942942end
943943
944- function ensure_setup! (ctx:: TestContext , setup :: Symbol , setups :: Vector{ TestSetup} , logs:: Symbol )
944+ function ensure_setup! (ctx:: TestContext , ts :: TestSetup , logs:: Symbol )
945945 mods = ctx. setups_evaled
946946 @lock mods. lock begin
947- mod = get (mods. modules, setup , nothing )
947+ mod = get (mods. modules, ts . name , nothing )
948948 if mod != = nothing
949949 # we've eval-ed this module before, so just return the module name
950950 return nameof (mod)
951951 end
952- # we haven't eval-ed this module before, so we need to eval it
953- i = findfirst (s -> s. name == setup, setups)
954- if i === nothing
955- # if the setup hasn't been eval-ed before and we don't have it
956- # in our testsetups, then it was never found during including
957- # in that case, we return the expected test setup module name
958- # which will turn into a `using $setup` in the test item
959- # which will throw an appropriate error
960- return setup
961- end
962- ts = setups[i]
963- # In case the setup fails to eval, we discard its logs -- the setup will be
964- # attempted to eval for each of the dependent test items and we'd for each
965- # failed test item, we'd print the cumulative logs from all the previous attempts.
952+ # We haven't eval-ed this module before, so we need to eval it.
953+ # In case the setup fails to eval, we discard its logs -- we will attempt to eval
954+ # this testsetup for each of the dependent test items, and then for each failed
955+ # test item, we'd print the cumulative logs from all the previous attempts.
966956 isassigned (ts. logstore) && close (ts. logstore[])
967957 ts. logstore[] = open (logpath (ts), " w" )
968958 mod_expr = :(module $ (gensym (ts. name)) end )
@@ -972,7 +962,7 @@ function ensure_setup!(ctx::TestContext, setup::Symbol, setups::Vector{TestSetup
972962 with_source_path (() -> Core. eval (Main, mod_expr), ts. file)
973963 end
974964 # add the new module to our TestSetupModules
975- mods. modules[setup ] = newmod
965+ mods. modules[ts . name ] = newmod
976966 return nameof (newmod)
977967 end
978968end
@@ -1020,9 +1010,9 @@ function runtestitem(ti::TestItem; kw...)
10201010 # make a fresh TestSetupModules for each testitem run
10211011 GLOBAL_TEST_CONTEXT_FOR_TESTING. setups_evaled = TestSetupModules ()
10221012 empty! (ti. testsetups)
1023- for setup in ti. setups
1024- ts = get (GLOBAL_TEST_SETUPS_FOR_TESTING, setup , nothing )
1025- ts != = nothing && push! (ti. testsetups, ts)
1013+ for setup_name in ti. setups
1014+ ts = get (GLOBAL_TEST_SETUPS_FOR_TESTING, setup_name , nothing )
1015+ ts != = nothing && push! (ti. testsetups, setup_name => ts)
10261016 end
10271017 runtestitem (ti, GLOBAL_TEST_CONTEXT_FOR_TESTING; kw... )
10281018end
@@ -1071,23 +1061,24 @@ function runtestitem(
10711061 prev = get (task_local_storage (), :__TESTITEM_ACTIVE__ , false )
10721062 task_local_storage ()[:__TESTITEM_ACTIVE__ ] = true
10731063 try
1074- for setup in ti. setups
1075- # TODO (nhd): Consider implementing some affinity to setups, so that we can
1076- # prefer to send testitems to the workers that have already eval'd setups.
1077- # Or maybe allow user-configurable grouping of test items by worker?
1078- # Or group them by file by default?
1079-
1064+ for (setup_name, ts) in ti. testsetups
10801065 # ensure setup has been evaled before
1081- @debugv 1 " Ensuring setup for test item $(repr (name)) $(setup )$(_on_worker ()) ."
1082- ts_mod = ensure_setup! (ctx, setup, ti . testsetups , logs)
1066+ @debugv 1 " Ensuring setup for test item $(repr (name)) $(setup_name )$(_on_worker ()) ."
1067+ ts_mod = ensure_setup! (ctx, ts , logs)
10831068 # eval using in our @testitem module
1084- @debugv 1 " Importing setup for test item $(repr (name)) $(setup )$(_on_worker ()) ."
1069+ @debugv 1 " Importing setup for test item $(repr (name)) $(setup_name )$(_on_worker ()) ."
10851070 # We look up the testsetups from Main (since tests are eval'd in their own
10861071 # temporary anonymous module environment.)
10871072 push! (body. args, Expr (:using , Expr (:., :Main , ts_mod)))
10881073 # ts_mod is a gensym'd name so that setup modules don't clash
10891074 # so we set a const alias inside our @testitem module to make things work
1090- push! (body. args, :(const $ setup = $ ts_mod))
1075+ push! (body. args, :(const $ setup_name = $ ts_mod))
1076+ end
1077+ for setup_name in setdiff (ti. setups, keys (ti. testsetups))
1078+ # if the setup was requested but is not in our testsetups, then it was never
1079+ # found when including files. We still add `using $setup` in the test item
1080+ # so that we throw an appropriate error when running the test item.
1081+ push! (body. args, Expr (:using , Expr (:., :Main , setup_name)))
10911082 end
10921083 @debugv 1 " Setup for test item $(repr (name)) done$(_on_worker ()) ."
10931084
@@ -1145,7 +1136,7 @@ function runtestitem(
11451136 end
11461137 finally
11471138 # Make sure all test setup logs are commited to file
1148- foreach (ts-> isassigned (ts. logstore) && flush (ts. logstore[]), ti. testsetups)
1139+ foreach (ts-> isassigned (ts. logstore) && flush (ts. logstore[]), values ( ti. testsetups) )
11491140 ts1 = Test. pop_testset ()
11501141 task_local_storage ()[:__TESTITEM_ACTIVE__ ] = prev
11511142 @assert ts1 === ts
0 commit comments