@@ -785,14 +785,14 @@ function include_testfiles!(project_name, projectfile, paths, ti_filter::TestIte
785
785
# we set it below in tls as __RE_TEST_SETUPS__ for each included file
786
786
setup_channel = Channel {Pair{Symbol, TestSetup}} (Inf )
787
787
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)
791
791
@warn " Encountered duplicate @testsetup with name: `$name `. Replacing..."
792
792
end
793
- setups [name] = setup
793
+ testsetups [name] = ts
794
794
end
795
- return setups
795
+ return testsetups
796
796
end
797
797
hidden_re = r" \.\w "
798
798
@sync for (root, d, files) in Base. walkdir (project_root)
@@ -844,21 +844,21 @@ function include_testfiles!(project_name, projectfile, paths, ti_filter::TestIte
844
844
# prune empty directories/files
845
845
close (setup_channel)
846
846
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)
852
852
# set a unique number for each testitem
853
- x . number[] = i
853
+ ti . number[] = i
854
854
# 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 ])
858
858
end
859
859
end
860
860
end
861
- return ti, setups # only returned for testing
861
+ return tis, testsetups # only returned for testing
862
862
end
863
863
864
864
function check_ids (testitems)
@@ -941,28 +941,18 @@ function with_source_path(f, path)
941
941
end
942
942
end
943
943
944
- function ensure_setup! (ctx:: TestContext , setup :: Symbol , setups :: Vector{ TestSetup} , logs:: Symbol )
944
+ function ensure_setup! (ctx:: TestContext , ts :: TestSetup , logs:: Symbol )
945
945
mods = ctx. setups_evaled
946
946
@lock mods. lock begin
947
- mod = get (mods. modules, setup , nothing )
947
+ mod = get (mods. modules, ts . name , nothing )
948
948
if mod != = nothing
949
949
# we've eval-ed this module before, so just return the module name
950
950
return nameof (mod)
951
951
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.
966
956
isassigned (ts. logstore) && close (ts. logstore[])
967
957
ts. logstore[] = open (logpath (ts), " w" )
968
958
mod_expr = :(module $ (gensym (ts. name)) end )
@@ -972,7 +962,7 @@ function ensure_setup!(ctx::TestContext, setup::Symbol, setups::Vector{TestSetup
972
962
with_source_path (() -> Core. eval (Main, mod_expr), ts. file)
973
963
end
974
964
# add the new module to our TestSetupModules
975
- mods. modules[setup ] = newmod
965
+ mods. modules[ts . name ] = newmod
976
966
return nameof (newmod)
977
967
end
978
968
end
@@ -1020,9 +1010,9 @@ function runtestitem(ti::TestItem; kw...)
1020
1010
# make a fresh TestSetupModules for each testitem run
1021
1011
GLOBAL_TEST_CONTEXT_FOR_TESTING. setups_evaled = TestSetupModules ()
1022
1012
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)
1026
1016
end
1027
1017
runtestitem (ti, GLOBAL_TEST_CONTEXT_FOR_TESTING; kw... )
1028
1018
end
@@ -1071,23 +1061,24 @@ function runtestitem(
1071
1061
prev = get (task_local_storage (), :__TESTITEM_ACTIVE__ , false )
1072
1062
task_local_storage ()[:__TESTITEM_ACTIVE__ ] = true
1073
1063
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
1080
1065
# 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)
1083
1068
# 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 ()) ."
1085
1070
# We look up the testsetups from Main (since tests are eval'd in their own
1086
1071
# temporary anonymous module environment.)
1087
1072
push! (body. args, Expr (:using , Expr (:., :Main , ts_mod)))
1088
1073
# ts_mod is a gensym'd name so that setup modules don't clash
1089
1074
# 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)))
1091
1082
end
1092
1083
@debugv 1 " Setup for test item $(repr (name)) done$(_on_worker ()) ."
1093
1084
@@ -1145,7 +1136,7 @@ function runtestitem(
1145
1136
end
1146
1137
finally
1147
1138
# 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) )
1149
1140
ts1 = Test. pop_testset ()
1150
1141
task_local_storage ()[:__TESTITEM_ACTIVE__ ] = prev
1151
1142
@assert ts1 === ts
0 commit comments