Skip to content

Commit e8280f0

Browse files
committed
make recoverable invalid @testset ... constructions
This matters when Revise is active: if an invalid construction was written, e.g. `@testset "a"` (without a body), `ReTest` couldn't be cleared of the error, even if the faulty testset was deleted, i.e. a restart was necessary. Now we just log the error and discard the testset.
1 parent e19e4f6 commit e8280f0

File tree

2 files changed

+37
-7
lines changed

2 files changed

+37
-7
lines changed

src/ReTest.jl

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,8 @@ function replace_ts(source, mod, x::Expr, parent)
9494
name = x.args[1]
9595
if name === Symbol("@testset")
9696
@assert x.args[2] isa LineNumberNode
97-
ts, hasbroken = parse_ts(source, mod, Tuple(x.args[3:end]), parent)
98-
parent !== nothing && push!(parent.children, ts)
97+
ts, hasbroken = parse_ts(x.args[2], mod, Tuple(x.args[3:end]), parent)
98+
ts !== nothing && parent !== nothing && push!(parent.children, ts)
9999
ts, false # hasbroken counts only "proper" @test_broken, not recursive ones
100100
elseif name === Symbol("@test_broken")
101101
x, true
@@ -116,30 +116,38 @@ function replace_ts(source, mod, x::Expr, parent)
116116
x, false
117117
else @label default
118118
body_br = map(z -> replace_ts(source, mod, z, parent), x.args)
119+
filter!(x -> first(x) !== nothing, body_br)
119120
Expr(x.head, first.(body_br)...), any(last.(body_br))
120121
end
121122
end
122123

123124
replace_ts(source, mod, x, _) = x, false
124125

125126
# create a TestsetExpr from @testset's args
126-
function parse_ts(source, mod, args::Tuple, parent=nothing)
127+
function parse_ts(source::LineNumberNode, mod::Module, args::Tuple, parent=nothing)
128+
function tserror(msg)
129+
@error msg _file=String(source.file) _line=source.line _module=mod
130+
nothing, false
131+
end
132+
127133
local desc
128134
options = Options()
129135
for arg in args[1:end-1]
130136
if arg isa String || Meta.isexpr(arg, :string)
131137
desc = arg
132138
elseif Meta.isexpr(arg, :(=))
133-
arg.args[1] in fieldnames(Options) || error("unsupported @testset option")
139+
arg.args[1] in fieldnames(Options) ||
140+
return tserror("unsupported @testset option")
134141
# TODO: make that work with non-literals:
135142
setfield!(options, arg.args[1], arg.args[2])
136143
else
137-
error("unsupported @testset")
144+
return tserror("unsupported @testset")
138145
end
139146
end
140147

141148
body = args[end]
142-
isa(body, Expr) || error("Expected begin/end block or for loop as argument to @testset")
149+
isa(body, Expr) ||
150+
return tserror("expected begin/end block or for loop as argument to @testset")
143151
if body.head === :for
144152
tsbody = body.args[2]
145153
loops = body.args[1]
@@ -165,7 +173,7 @@ function parse_ts(source, mod, args::Tuple, parent=nothing)
165173
desc = "anonym $(randstring('0':'9'))"
166174
end
167175
else
168-
error("Expected begin/end block or for loop as argument to @testset")
176+
return tserror("expected begin/end block or for loop as argument to @testset")
169177
end
170178

171179
ts = TestsetExpr(source, mod, desc, options, loops, parent)
@@ -422,6 +430,7 @@ function updatetests!(mod::Module, dup::Bool)
422430
# the last version; should we delete all of the versions in this case?
423431
for (tsargs, source) in news
424432
ts, hasbroken = parse_ts(source, mod, tsargs)
433+
ts === nothing && continue
425434
idx = get!(map, ts.desc, length(tests) + 1)
426435
if idx == length(tests) + 1
427436
push!(tests, ts)

test/runtests.jl

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,27 @@ end
827827
end
828828

829829

830+
module TestsetErrors
831+
using ReTest
832+
833+
@testset "a" notexistingoption=0 begin end
834+
@testset "b" {badsyntax} begin end
835+
@testset "c"
836+
@testset "d" let; end
837+
end
838+
839+
@chapter "TestsetErrors" begin
840+
Test.@testset "TestsetErrors" begin
841+
@test_logs (
842+
:error, "unsupported @testset option") (
843+
:error, "unsupported @testset" ) (
844+
:error, "expected begin/end block or for loop as argument to @testset") (
845+
:error, "expected begin/end block or for loop as argument to @testset"
846+
) TestsetErrors.runtests()
847+
end
848+
end
849+
850+
830851
# * Failing ..................................................................
831852

832853
module Failing

0 commit comments

Comments
 (0)