Skip to content

Commit

Permalink
Test: support multiple assignments for @testset let (JuliaLang#50151)
Browse files Browse the repository at this point in the history
Nested `ContextTestset` is  supported, so we can stack it when there are
multiple assignments in a given `let` block.

```julia
julia> @testset let logi = log(im), op = !iszero
           @test imag(logi) == π/2
           @test op(real(logi))
       end
Test Failed at none:3
  Expression: !(iszero(real(logi)))
     Context: logi = 0.0 + 1.5707963267948966im
              op = !iszero

ERROR: There was an error during testing
```
  • Loading branch information
aviatesk committed Jun 13, 2023
1 parent f007c01 commit 0d89d8b
Showing 1 changed file with 46 additions and 16 deletions.
62 changes: 46 additions & 16 deletions stdlib/Test/src/Test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1351,11 +1351,11 @@ function _check_testset(testsettype, testsetname)
end

"""
@testset [CustomTestSet] [option=val ...] ["description"] begin ... end
@testset [CustomTestSet] [option=val ...] ["description \$v"] for v in (...) ... end
@testset [CustomTestSet] [option=val ...] ["description \$v, \$w"] for v in (...), w in (...) ... end
@testset [CustomTestSet] [option=val ...] ["description"] foo()
@testset let v = (...) ... end
@testset [CustomTestSet] [options...] ["description"] begin test_ex end
@testset [CustomTestSet] [options...] ["description \$v"] for v in itr test_ex end
@testset [CustomTestSet] [options...] ["description \$v, \$w"] for v in itrv, w in itrw test_ex end
@testset [CustomTestSet] [options...] ["description"] test_func()
@testset let v = v, w = w; test_ex; end
# With begin/end or function call
Expand All @@ -1380,7 +1380,7 @@ accepts three boolean options:
This can also be set globally via the env var `JULIA_TEST_FAILFAST`.
!!! compat "Julia 1.8"
`@testset foo()` requires at least Julia 1.8.
`@testset test_func()` requires at least Julia 1.8.
!!! compat "Julia 1.9"
`failfast` requires at least Julia 1.9.
Expand Down Expand Up @@ -1436,6 +1436,9 @@ parent test set (with the context object appended to any failing tests.)
!!! compat "Julia 1.9"
`@testset let` requires at least Julia 1.9.
!!! compat "Julia 1.10"
Multiple `let` assignements are supported since Julia 1.10.
## Examples
```jldoctest
julia> @testset let logi = log(im)
Expand All @@ -1446,6 +1449,17 @@ Test Failed at none:3
Expression: !(iszero(real(logi)))
Context: logi = 0.0 + 1.5707963267948966im
ERROR: There was an error during testing
julia> @testset let logi = log(im), op = !iszero
@test imag(logi) == π/2
@test op(real(logi))
end
Test Failed at none:3
Expression: op(real(logi))
Context: logi = 0.0 + 1.5707963267948966im
op = !iszero
ERROR: There was an error during testing
```
"""
Expand Down Expand Up @@ -1477,30 +1491,46 @@ trigger_test_failure_break(@nospecialize(err)) =
"""
Generate the code for an `@testset` with a `let` argument.
"""
function testset_context(args, tests, source)
function testset_context(args, ex, source)
desc, testsettype, options = parse_testset_args(args[1:end-1])
if desc !== nothing || testsettype !== nothing
# Reserve this syntax if we ever want to allow this, but for now,
# just do the transparent context test set.
error("@testset with a `let` argument cannot be customized")
end

assgn = tests.args[1]
if !isa(assgn, Expr) || assgn.head !== :(=)
error("`@testset let` must have exactly one assignment")
let_ex = ex.args[1]

if Meta.isexpr(let_ex, :(=))
contexts = Any[let_ex.args[1]]
elseif Meta.isexpr(let_ex, :block)
contexts = Any[]
for assign_ex in let_ex.args
if Meta.isexpr(assign_ex, :(=))
push!(contexts, assign_ex.args[1])
else
error("Malformed `let` expression is given")
end
end
else
error("Malformed `let` expression is given")
end
assignee = assgn.args[1]
reverse!(contexts)

test_ex = ex.args[2]

tests.args[2] = quote
$push_testset($(ContextTestSet)($(QuoteNode(assignee)), $assignee; $options...))
ex.args[2] = quote
$(map(contexts) do context
:($push_testset($(ContextTestSet)($(QuoteNode(context)), $context; $options...)))
end...)
try
$(tests.args[2])
$(test_ex)
finally
$pop_testset()
$(map(_->:($pop_testset()), contexts)...)
end
end

return esc(tests)
return esc(ex)
end

"""
Expand Down

0 comments on commit 0d89d8b

Please sign in to comment.