@@ -16,17 +16,18 @@ __init__() = INLINE_TEST[] = gensym()
16
16
function tests (m)
17
17
inline_test:: Symbol = m ∈ (InlineTest, InlineTest. InlineTestTest) ? :__INLINE_TEST__ : INLINE_TEST[]
18
18
if ! isdefined (m, inline_test)
19
- @eval m $ inline_test = Expr[]
19
+ @eval m $ inline_test = Tuple{ Expr,Union{String,Missing},Bool} []
20
20
end
21
21
getfield (m, inline_test)
22
22
end
23
23
24
24
replacetestset (x) = x, false
25
25
26
26
# replace unqualified `@testset` by @testsetr
27
- # return also (as 2nd element) whether the expression contains a (possibly nested) @testset
27
+ # return also (as 3nd element) whether the expression contains a (possibly nested) @testset
28
28
# (if a testset is "final", i.e. without nested testsets, then the Regex matching logic
29
29
# is different: we then don't use "partial matching")
30
+ # the 2nd returned element is whether the testset is final (used only in `addtest`)
30
31
function replacetestset (x:: Expr )
31
32
if x. head === :macrocall && x. args[1 ] === Symbol (" @testset" )
32
33
body = map (replacetestset, x. args[2 : end ])
@@ -35,17 +36,21 @@ function replacetestset(x::Expr)
35
36
:($ (Testset. FINAL[]) = $ final),
36
37
Expr (:macrocall , Expr (:., :InlineTest , QuoteNode (Symbol (" @testsetr" ))),
37
38
map (first, body)... )),
38
- true )
39
+ final, true )
39
40
else
40
41
body = map (replacetestset, x. args)
41
42
(Expr (x. head, map (first, body)... ),
42
- any (last, body))
43
+ missing , any (last, body)) # missing: a non-testset doesn't have a "final" attribute...
43
44
end
44
45
end
45
46
46
47
function addtest (args:: Tuple , m:: Module )
47
- ts, _ = replacetestset (:(@testset ($ (args... ))))
48
- push! (tests (m), ts)
48
+ desc = args[1 ] isa String ? args[1 ] : missing
49
+ # args[1] might not be a string if none was passed, or for a testset-for with
50
+ # interpolated loop variable (in which case it's difficult to statically know the
51
+ # final description)
52
+ ts, final, _ = replacetestset (:(@testset ($ (args... ))))
53
+ push! (tests (m), (ts, desc, final))
49
54
nothing
50
55
end
51
56
@@ -79,11 +84,15 @@ function runtests(m::Module, regex::Regex = r""; wrap::Bool=false)
79
84
if wrap
80
85
Core. eval (m, :(InlineTest. Test. @testset $ (" Tests for module $m " ) begin
81
86
let $ (Testset. REGEX[]) = ($ partial, $ regex)
82
- $ (tests (m)... )
87
+ $ (map (first, tests (m) )... )
83
88
end
84
89
end ))
85
90
else
86
- for ts in tests (m)
91
+ for (ts, desc, final) in tests (m)
92
+ # bypass evaluation if we know statically that testset won't be run
93
+ if desc isa String && final && ! occursin (regex, desc) # TODO : handle non-final case
94
+ continue
95
+ end
87
96
# it's faster to evel in a loop than to eval a block containing tests(m)
88
97
Core. eval (m, :(let $ (Testset. REGEX[]) = ($ partial, $ regex)
89
98
$ ts
0 commit comments