Skip to content

Commit

Permalink
Merge pull request JuliaLang#22296 from JuliaLang/cv/test-results-ise…
Browse files Browse the repository at this point in the history
…qual

Show evaluated expr when `@test isequal(...)` fails
  • Loading branch information
tkelman committed Jun 24, 2017
2 parents 3808de9 + 3b3302b commit bef5811
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 11 deletions.
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ Library improvements

* Added `unique!` which is an inplace version of `unique` ([#20549]).

* `@test isequal(x, y)` and `@test isapprox(x, y)` now prints an evaluated expression when
the test fails ([#22296]).

Compiler/Runtime improvements
-----------------------------

Expand Down
40 changes: 29 additions & 11 deletions base/test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ function Base.show(io::IO, t::Pass)
if t.test_type == :test_throws
# The correct type of exception was thrown
print(io, "\n Thrown: ", typeof(t.value))
elseif t.test_type == :test && isa(t.data,Expr) && t.data.head == :comparison
elseif t.test_type == :test && isa(t.data, Expr)
# The test was an expression, so display the term-by-term
# evaluated version as well
print(io, "\n Evaluated: ", t.data)
Expand Down Expand Up @@ -106,7 +106,7 @@ function Base.show(io::IO, t::Fail)
# An exception was expected, but no exception was thrown
print(io, "\n Expected: ", t.data)
print(io, "\n No exception thrown")
elseif t.test_type == :test && isa(t.data,Expr) && t.data.head == :comparison
elseif t.test_type == :test && isa(t.data, Expr)
# The test was an expression, so display the term-by-term
# evaluated version as well
print(io, "\n Evaluated: ", t.data)
Expand Down Expand Up @@ -188,20 +188,31 @@ struct Threw <: ExecutionResult
backtrace
end

function eval_comparison(evaluated::Expr, quoted::Expr)
function eval_test(evaluated::Expr, quoted::Expr)
res = true
i = 1
args = evaluated.args
quoted_args = quoted.args
n = length(args)
while i < n
a, op, b = args[i], args[i+1], args[i+2]
if res
res = op(a, b) === true # Keep `res` type stable
if evaluated.head == :comparison
while i < n
a, op, b = args[i], args[i+1], args[i+2]
if res
res = op(a, b) === true # Keep `res` type stable
end
quoted_args[i] = a
quoted_args[i+2] = b
i += 2
end

elseif evaluated.head == :call
op = args[1]
res = op(args[2:n]...) === true
for i in 2:n
quoted_args[i] = args[i]
end
quoted_args[i] = a
quoted_args[i+2] = b
i += 2
else
throw(ArgumentError("Unhandled expression type: $(evaluated.head)"))
end
Returned(res, quoted)
end
Expand Down Expand Up @@ -307,10 +318,17 @@ function get_test_result(ex)
# pass all terms of the comparison to `eval_comparison`, as an Expr
escaped_terms = [esc(arg) for arg in ex.args]
quoted_terms = [QuoteNode(arg) for arg in ex.args]
testret = :(eval_comparison(
testret = :(eval_test(
Expr(:comparison, $(escaped_terms...)),
Expr(:comparison, $(quoted_terms...)),
))
elseif isa(ex, Expr) && ex.head == :call && ex.args[1] in (:isequal, :isapprox)
escaped_terms = [esc(arg) for arg in ex.args]
quoted_terms = [QuoteNode(arg) for arg in ex.args]
testret = :(eval_test(
Expr(:call, $(escaped_terms...)),
Expr(:call, $(quoted_terms...)),
))
else
testret = :(Returned($(esc(ex)), nothing))
end
Expand Down
16 changes: 16 additions & 0 deletions test/test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
let g = Int[], f = (x) -> (push!(g, x); x)
@test f(1) == 1
@test g == [1]

empty!(g)
@test isequal(f(2), 2)
@test g == [2]
end

# Test @test_broken with fail
Expand Down Expand Up @@ -74,6 +78,10 @@ fails = @testset NoThrowTestSet begin
@test 1+0 == 2+0 == 3+0
# Fail - comparison call
@test ==(1 - 2, 2 - 1)
# Fail - isequal
@test isequal(0 / 0, 1 / 0)
# Fail - isapprox
@test isapprox(0 / 1, -1 / 0)
# Error - unexpected pass
@test_broken true
end
Expand Down Expand Up @@ -106,6 +114,14 @@ str = sprint(show, fails[6])
@test contains(str, "Evaluated: -1 == 1")

str = sprint(show, fails[7])
@test contains(str, "Expression: isequal(0 / 0, 1 / 0)")
@test contains(str, "Evaluated: isequal(NaN, Inf)")

str = sprint(show, fails[8])
@test contains(str, "Expression: isapprox(0 / 1, -1 / 0)")
@test contains(str, "Evaluated: isapprox(0.0, -Inf)")

str = sprint(show, fails[9])
@test contains(str, "Unexpected Pass")
@test contains(str, "Expression: true")

Expand Down

0 comments on commit bef5811

Please sign in to comment.