@@ -665,14 +665,14 @@ function include_testfiles!(project_name, projectfile, paths, shouldrun, verbose
665
665
# we set it below in tls as __RE_TEST_SETUPS__ for each included file
666
666
setup_channel = Channel {Pair{Symbol, TestSetup}} (Inf )
667
667
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)
671
671
@warn " Encountered duplicate @testsetup with name: `$name `. Replacing..."
672
672
end
673
- setups [name] = setup
673
+ testsetups [name] = ts
674
674
end
675
- return setups
675
+ return testsetups
676
676
end
677
677
hidden_re = r" \.\w "
678
678
@sync for (root, d, files) in Base. walkdir (project_root)
@@ -724,21 +724,21 @@ function include_testfiles!(project_name, projectfile, paths, shouldrun, verbose
724
724
# prune empty directories/files
725
725
close (setup_channel)
726
726
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)
732
732
# set a unique number for each testitem
733
- x . number[] = i
733
+ ti . number[] = i
734
734
# 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 ])
738
738
end
739
739
end
740
740
end
741
- return ti, setups # only returned for testing
741
+ return tis, testsetups # only returned for testing
742
742
end
743
743
744
744
function check_ids (testitems)
@@ -821,28 +821,18 @@ function with_source_path(f, path)
821
821
end
822
822
end
823
823
824
- function ensure_setup! (ctx:: TestContext , setup :: Symbol , setups :: Vector{ TestSetup} , logs:: Symbol )
824
+ function ensure_setup! (ctx:: TestContext , ts :: TestSetup , logs:: Symbol )
825
825
mods = ctx. setups_evaled
826
826
@lock mods. lock begin
827
- mod = get (mods. modules, setup , nothing )
827
+ mod = get (mods. modules, ts . name , nothing )
828
828
if mod != = nothing
829
829
# we've eval-ed this module before, so just return the module name
830
830
return nameof (mod)
831
831
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.
846
836
isassigned (ts. logstore) && close (ts. logstore[])
847
837
ts. logstore[] = open (logpath (ts), " w" )
848
838
mod_expr = :(module $ (gensym (ts. name)) end )
@@ -852,7 +842,7 @@ function ensure_setup!(ctx::TestContext, setup::Symbol, setups::Vector{TestSetup
852
842
with_source_path (() -> Core. eval (Main, mod_expr), ts. file)
853
843
end
854
844
# add the new module to our TestSetupModules
855
- mods. modules[setup ] = newmod
845
+ mods. modules[ts . name ] = newmod
856
846
return nameof (newmod)
857
847
end
858
848
end
@@ -900,9 +890,9 @@ function runtestitem(ti::TestItem; kw...)
900
890
# make a fresh TestSetupModules for each testitem run
901
891
GLOBAL_TEST_CONTEXT_FOR_TESTING. setups_evaled = TestSetupModules ()
902
892
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)
906
896
end
907
897
runtestitem (ti, GLOBAL_TEST_CONTEXT_FOR_TESTING; kw... )
908
898
end
@@ -940,23 +930,24 @@ function runtestitem(
940
930
prev = get (task_local_storage (), :__TESTITEM_ACTIVE__ , false )
941
931
task_local_storage ()[:__TESTITEM_ACTIVE__ ] = true
942
932
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
949
934
# 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)
952
937
# 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 ()) ."
954
939
# We look up the testsetups from Main (since tests are eval'd in their own
955
940
# temporary anonymous module environment.)
956
941
push! (body. args, Expr (:using , Expr (:., :Main , ts_mod)))
957
942
# ts_mod is a gensym'd name so that setup modules don't clash
958
943
# 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)))
960
951
end
961
952
@debugv 1 " Setup for test item $(repr (name)) done$(_on_worker ()) ."
962
953
@@ -994,7 +985,7 @@ function runtestitem(
994
985
LineNumberNode (ti. line, ti. file)))
995
986
finally
996
987
# 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) )
998
989
ts1 = Test. pop_testset ()
999
990
task_local_storage ()[:__TESTITEM_ACTIVE__ ] = prev
1000
991
@assert ts1 === ts
0 commit comments