@@ -665,14 +665,14 @@ function include_testfiles!(project_name, projectfile, paths, shouldrun, verbose
665665 # we set it below in tls as __RE_TEST_SETUPS__ for each included file
666666 setup_channel = Channel {Pair{Symbol, TestSetup}} (Inf )
667667 setup_task = @spawn begin
668- setups = Dict {Symbol, TestSetup} ()
669- for (name, setup ) in setup_channel
670- if haskey (setups , name)
668+ testsetups = Dict {Symbol, TestSetup} ()
669+ for (name, ts ) in setup_channel
670+ if haskey (testsetups , name)
671671 @warn " Encountered duplicate @testsetup with name: `$name `. Replacing..."
672672 end
673- setups [name] = setup
673+ testsetups [name] = ts
674674 end
675- return setups
675+ return testsetups
676676 end
677677 hidden_re = r" \.\w "
678678 @sync for (root, d, files) in Base. walkdir (project_root)
@@ -724,21 +724,21 @@ function include_testfiles!(project_name, projectfile, paths, shouldrun, verbose
724724 # prune empty directories/files
725725 close (setup_channel)
726726 prune! (root_node)
727- ti = TestItems (root_node)
728- flatten_testitems! (ti )
729- check_ids (ti . testitems)
730- setups = fetch (setup_task)
731- for (i, x ) in enumerate (ti . testitems)
727+ tis = TestItems (root_node)
728+ flatten_testitems! (tis )
729+ check_ids (tis . testitems)
730+ testsetups = fetch (setup_task)
731+ for (i, ti ) in enumerate (tis . testitems)
732732 # set a unique number for each testitem
733- x . number[] = i
733+ ti . number[] = i
734734 # populate testsetups for each testitem
735- for s in x . setups
736- if haskey (setups, s )
737- push! (x . testsetups, setups[s ])
735+ for setup_name in ti . setups
736+ if haskey (testsetups, setup_name )
737+ push! (ti . testsetups, setup_name => testsetups[setup_name ])
738738 end
739739 end
740740 end
741- return ti, setups # only returned for testing
741+ return tis, testsetups # only returned for testing
742742end
743743
744744function check_ids (testitems)
@@ -821,28 +821,18 @@ function with_source_path(f, path)
821821 end
822822end
823823
824- function ensure_setup! (ctx:: TestContext , setup :: Symbol , setups :: Vector{ TestSetup} , logs:: Symbol )
824+ function ensure_setup! (ctx:: TestContext , ts :: TestSetup , logs:: Symbol )
825825 mods = ctx. setups_evaled
826826 @lock mods. lock begin
827- mod = get (mods. modules, setup , nothing )
827+ mod = get (mods. modules, ts . name , nothing )
828828 if mod != = nothing
829829 # we've eval-ed this module before, so just return the module name
830830 return nameof (mod)
831831 end
832- # we haven't eval-ed this module before, so we need to eval it
833- i = findfirst (s -> s. name == setup, setups)
834- if i === nothing
835- # if the setup hasn't been eval-ed before and we don't have it
836- # in our testsetups, then it was never found during including
837- # in that case, we return the expected test setup module name
838- # which will turn into a `using $setup` in the test item
839- # which will throw an appropriate error
840- return setup
841- end
842- ts = setups[i]
843- # In case the setup fails to eval, we discard its logs -- the setup will be
844- # attempted to eval for each of the dependent test items and we'd for each
845- # failed test item, we'd print the cumulative logs from all the previous attempts.
832+ # We haven't eval-ed this module before, so we need to eval it.
833+ # In case the setup fails to eval, we discard its logs -- we will attempt to eval
834+ # this testsetup for each of the dependent test items, and then for each failed
835+ # test item, we'd print the cumulative logs from all the previous attempts.
846836 isassigned (ts. logstore) && close (ts. logstore[])
847837 ts. logstore[] = open (logpath (ts), " w" )
848838 mod_expr = :(module $ (gensym (ts. name)) end )
@@ -852,7 +842,7 @@ function ensure_setup!(ctx::TestContext, setup::Symbol, setups::Vector{TestSetup
852842 with_source_path (() -> Core. eval (Main, mod_expr), ts. file)
853843 end
854844 # add the new module to our TestSetupModules
855- mods. modules[setup ] = newmod
845+ mods. modules[ts . name ] = newmod
856846 return nameof (newmod)
857847 end
858848end
@@ -900,9 +890,9 @@ function runtestitem(ti::TestItem; kw...)
900890 # make a fresh TestSetupModules for each testitem run
901891 GLOBAL_TEST_CONTEXT_FOR_TESTING. setups_evaled = TestSetupModules ()
902892 empty! (ti. testsetups)
903- for setup in ti. setups
904- ts = get (GLOBAL_TEST_SETUPS_FOR_TESTING, setup , nothing )
905- ts != = nothing && push! (ti. testsetups, ts)
893+ for setup_name in ti. setups
894+ ts = get (GLOBAL_TEST_SETUPS_FOR_TESTING, setup_name , nothing )
895+ ts != = nothing && push! (ti. testsetups, setup_name => ts)
906896 end
907897 runtestitem (ti, GLOBAL_TEST_CONTEXT_FOR_TESTING; kw... )
908898end
@@ -940,23 +930,24 @@ function runtestitem(
940930 prev = get (task_local_storage (), :__TESTITEM_ACTIVE__ , false )
941931 task_local_storage ()[:__TESTITEM_ACTIVE__ ] = true
942932 try
943- for setup in ti. setups
944- # TODO (nhd): Consider implementing some affinity to setups, so that we can
945- # prefer to send testitems to the workers that have already eval'd setups.
946- # Or maybe allow user-configurable grouping of test items by worker?
947- # Or group them by file by default?
948-
933+ for (setup_name, ts) in ti. testsetups
949934 # ensure setup has been evaled before
950- @debugv 1 " Ensuring setup for test item $(repr (name)) $(setup )$(_on_worker ()) ."
951- ts_mod = ensure_setup! (ctx, setup, ti . testsetups , logs)
935+ @debugv 1 " Ensuring setup for test item $(repr (name)) $(setup_name )$(_on_worker ()) ."
936+ ts_mod = ensure_setup! (ctx, ts , logs)
952937 # eval using in our @testitem module
953- @debugv 1 " Importing setup for test item $(repr (name)) $(setup )$(_on_worker ()) ."
938+ @debugv 1 " Importing setup for test item $(repr (name)) $(setup_name )$(_on_worker ()) ."
954939 # We look up the testsetups from Main (since tests are eval'd in their own
955940 # temporary anonymous module environment.)
956941 push! (body. args, Expr (:using , Expr (:., :Main , ts_mod)))
957942 # ts_mod is a gensym'd name so that setup modules don't clash
958943 # so we set a const alias inside our @testitem module to make things work
959- push! (body. args, :(const $ setup = $ ts_mod))
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)))
960951 end
961952 @debugv 1 " Setup for test item $(repr (name)) done$(_on_worker ()) ."
962953
@@ -994,7 +985,7 @@ function runtestitem(
994985 LineNumberNode (ti. line, ti. file)))
995986 finally
996987 # Make sure all test setup logs are commited to file
997- foreach (ts-> isassigned (ts. logstore) && flush (ts. logstore[]), ti. testsetups)
988+ foreach (ts-> isassigned (ts. logstore) && flush (ts. logstore[]), values ( ti. testsetups) )
998989 ts1 = Test. pop_testset ()
999990 task_local_storage ()[:__TESTITEM_ACTIVE__ ] = prev
1000991 @assert ts1 === ts
0 commit comments