Skip to content

Commit e9380c0

Browse files
Merge pull request #19901 from JuliaLang/sk/testkws
`@test a ≈ b atol=ε`
2 parents 3d6fa35 + 83bf2db commit e9380c0

File tree

19 files changed

+220
-183
lines changed

19 files changed

+220
-183
lines changed

base/deprecated.jl

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1674,4 +1674,71 @@ iteratoreltype(::Type{Task}) = EltypeUnknown()
16741674

16751675
isempty(::Task) = error("isempty not defined for Tasks")
16761676

1677+
# BEGIN code from base/test.jl
1678+
approx_full(x::AbstractArray) = x
1679+
approx_full(x::Number) = x
1680+
approx_full(x) = full(x)
1681+
1682+
function test_approx_eq(va, vb, Eps, astr, bstr)
1683+
va = approx_full(va)
1684+
vb = approx_full(vb)
1685+
la, lb = length(linearindices(va)), length(linearindices(vb))
1686+
if la != lb
1687+
error("lengths of ", astr, " and ", bstr, " do not match: ",
1688+
"\n ", astr, " (length $la) = ", va,
1689+
"\n ", bstr, " (length $lb) = ", vb)
1690+
end
1691+
diff = real(zero(eltype(va)))
1692+
for (xa, xb) = zip(va, vb)
1693+
if isfinite(xa) && isfinite(xb)
1694+
diff = max(diff, abs(xa-xb))
1695+
elseif !isequal(xa,xb)
1696+
error("mismatch of non-finite elements: ",
1697+
"\n ", astr, " = ", va,
1698+
"\n ", bstr, " = ", vb)
1699+
end
1700+
end
1701+
1702+
if !isnan(Eps) && !(diff <= Eps)
1703+
sdiff = string("|", astr, " - ", bstr, "| <= ", Eps)
1704+
error("assertion failed: ", sdiff,
1705+
"\n ", astr, " = ", va,
1706+
"\n ", bstr, " = ", vb,
1707+
"\n difference = ", diff, " > ", Eps)
1708+
end
1709+
end
1710+
1711+
array_eps{T}(a::AbstractArray{Complex{T}}) = eps(float(maximum(x->(isfinite(x) ? abs(x) : T(NaN)), a)))
1712+
array_eps(a) = eps(float(maximum(x->(isfinite(x) ? abs(x) : oftype(x,NaN)), a)))
1713+
1714+
test_approx_eq(va, vb, astr, bstr) =
1715+
test_approx_eq(va, vb, 1E4*length(linearindices(va))*max(array_eps(va), array_eps(vb)), astr, bstr)
1716+
1717+
"""
1718+
@test_approx_eq_eps(a, b, tol)
1719+
1720+
Test two floating point numbers `a` and `b` for equality taking into account
1721+
a margin of tolerance given by `tol`.
1722+
"""
1723+
macro test_approx_eq_eps(a, b, c)
1724+
Base.depwarn(string("@test_approx_eq_eps is deprecated, use `@test ", a, "", b, " atol=", c, "` instead"),
1725+
Symbol("@test_approx_eq_eps"))
1726+
:(test_approx_eq($(esc(a)), $(esc(b)), $(esc(c)), $(string(a)), $(string(b))))
1727+
end
1728+
export @test_approx_eq_eps
1729+
1730+
"""
1731+
@test_approx_eq(a, b)
1732+
1733+
Deprecated. Test two floating point numbers `a` and `b` for equality taking into
1734+
account small numerical errors.
1735+
"""
1736+
macro test_approx_eq(a, b)
1737+
Base.depwarn(string("@test_approx_eq is deprecated, use `@test ", a, "", b, "` instead"),
1738+
Symbol("@test_approx_eq"))
1739+
:(test_approx_eq($(esc(a)), $(esc(b)), $(string(a)), $(string(b))))
1740+
end
1741+
export @test_approx_eq
1742+
# END code from base/test.jl
1743+
16771744
# End deprecations scheduled for 0.6

base/test.jl

Lines changed: 49 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ module Test
1616
export @test, @test_throws, @test_broken, @test_skip, @test_warn, @test_nowarn
1717
export @testset
1818
# Legacy approximate testing functions, yet to be included
19-
export @test_approx_eq_eps, @inferred
19+
export @inferred
2020
export detect_ambiguities
2121
export GenericString
2222

@@ -203,29 +203,65 @@ end
203203

204204
const comparison_prec = Base.operator_precedence(:(==))
205205

206+
"""
207+
test_expr!(ex, kws...)
208+
209+
Preprocess test expressions of function calls with trailing keyword arguments
210+
so that e.g. `@test a ≈ b atol=ε` means `@test ≈(a, b, atol=ε)`.
211+
"""
212+
test_expr!(m, ex) = ex
213+
214+
function test_expr!(m, ex, kws...)
215+
ex isa Expr && ex.head == :call || @goto fail
216+
for kw in kws
217+
kw isa Expr && kw.head == :(=) || @goto fail
218+
kw.head = :kw
219+
push!(ex.args, kw)
220+
end
221+
return ex
222+
@label fail
223+
error("invalid test macro call: $m $ex $(join(kws," "))")
224+
end
225+
206226
# @test - check if the expression evaluates to true
207227
"""
208228
@test ex
229+
@test f(args...) key=val ...
209230
210231
Tests that the expression `ex` evaluates to `true`.
211232
Returns a `Pass` `Result` if it does, a `Fail` `Result` if it is
212233
`false`, and an `Error` `Result` if it could not be evaluated.
234+
235+
The `@test f(args...) key=val...` form is equivalent to writing
236+
`@test f(args..., key=val...)` which can be useful when the expression
237+
is a call using infix syntax such as approximate comparisons:
238+
239+
@test a ≈ b atol=ε
240+
241+
This is equivalent to the uglier test `@test ≈(a, b, atol=ε)`.
242+
It is an error to supply more than one expression unless the first
243+
is a call expression and the rest are assignments (`k=v`).
213244
"""
214-
macro test(ex)
245+
macro test(ex, kws...)
246+
test_expr!("@test", ex, kws...)
215247
orig_ex = Expr(:inert, ex)
216248
result = get_test_result(ex)
217249
:(do_test($result, $orig_ex))
218250
end
219251

220252
"""
221253
@test_broken ex
254+
@test_broken f(args...) key=val ...
222255
223256
Indicates a test that should pass but currently consistently fails.
224257
Tests that the expression `ex` evaluates to `false` or causes an
225258
exception. Returns a `Broken` `Result` if it does, or an `Error` `Result`
226259
if the expression evaluates to `true`.
260+
261+
The `@test_broken f(args...) key=val...` form works as for the `@test` macro.
227262
"""
228-
macro test_broken(ex)
263+
macro test_broken(ex, kws...)
264+
test_expr!("@test_broken", ex, kws...)
229265
orig_ex = Expr(:inert, ex)
230266
result = get_test_result(ex)
231267
# code to call do_test with execution result and original expr
@@ -234,12 +270,16 @@ end
234270

235271
"""
236272
@test_skip ex
273+
@test_skip f(args...) key=val ...
237274
238275
Marks a test that should not be executed but should be included in test
239276
summary reporting as `Broken`. This can be useful for tests that intermittently
240277
fail, or tests of not-yet-implemented functionality.
278+
279+
The `@test_skip f(args...) key=val...` form works as for the `@test` macro.
241280
"""
242-
macro test_skip(ex)
281+
macro test_skip(ex, kws...)
282+
test_expr!("@test_skip", ex, kws...)
243283
orig_ex = Expr(:inert, ex)
244284
testres = :(Broken(:skipped, $orig_ex))
245285
:(record(get_testset(), $testres))
@@ -326,6 +366,7 @@ end
326366
@test_throws extype ex
327367
328368
Tests that the expression `ex` throws an exception of type `extype`.
369+
Note that `@test_throws` does not support a trailing keyword form.
329370
"""
330371
macro test_throws(extype, ex)
331372
orig_ex = Expr(:inert, ex)
@@ -960,71 +1001,6 @@ function get_testset_depth()
9601001
return length(testsets)
9611002
end
9621003

963-
#-----------------------------------------------------------------------
964-
# Legacy approximate testing functions, yet to be included
965-
966-
approx_full(x::AbstractArray) = x
967-
approx_full(x::Number) = x
968-
approx_full(x) = full(x)
969-
970-
function test_approx_eq(va, vb, Eps, astr, bstr)
971-
va = approx_full(va)
972-
vb = approx_full(vb)
973-
la, lb = length(linearindices(va)), length(linearindices(vb))
974-
if la != lb
975-
error("lengths of ", astr, " and ", bstr, " do not match: ",
976-
"\n ", astr, " (length $la) = ", va,
977-
"\n ", bstr, " (length $lb) = ", vb)
978-
end
979-
diff = real(zero(eltype(va)))
980-
for (xa, xb) = zip(va, vb)
981-
if isfinite(xa) && isfinite(xb)
982-
diff = max(diff, abs(xa-xb))
983-
elseif !isequal(xa,xb)
984-
error("mismatch of non-finite elements: ",
985-
"\n ", astr, " = ", va,
986-
"\n ", bstr, " = ", vb)
987-
end
988-
end
989-
990-
if !isnan(Eps) && !(diff <= Eps)
991-
sdiff = string("|", astr, " - ", bstr, "| <= ", Eps)
992-
error("assertion failed: ", sdiff,
993-
"\n ", astr, " = ", va,
994-
"\n ", bstr, " = ", vb,
995-
"\n difference = ", diff, " > ", Eps)
996-
end
997-
end
998-
999-
array_eps{T}(a::AbstractArray{Complex{T}}) = eps(float(maximum(x->(isfinite(x) ? abs(x) : T(NaN)), a)))
1000-
array_eps(a) = eps(float(maximum(x->(isfinite(x) ? abs(x) : oftype(x,NaN)), a)))
1001-
1002-
test_approx_eq(va, vb, astr, bstr) =
1003-
test_approx_eq(va, vb, 1E4*length(linearindices(va))*max(array_eps(va), array_eps(vb)), astr, bstr)
1004-
1005-
"""
1006-
@test_approx_eq_eps(a, b, tol)
1007-
1008-
Test two floating point numbers `a` and `b` for equality taking into account
1009-
a margin of tolerance given by `tol`.
1010-
"""
1011-
macro test_approx_eq_eps(a, b, c)
1012-
:(test_approx_eq($(esc(a)), $(esc(b)), $(esc(c)), $(string(a)), $(string(b))))
1013-
end
1014-
1015-
"""
1016-
@test_approx_eq(a, b)
1017-
1018-
Deprecated. Test two floating point numbers `a` and `b` for equality taking into
1019-
account small numerical errors.
1020-
"""
1021-
macro test_approx_eq(a, b)
1022-
Base.depwarn(string("@test_approx_eq is deprecated, use `@test ", a, "", b, "` instead"),
1023-
Symbol("@test_approx_eq"))
1024-
:(test_approx_eq($(esc(a)), $(esc(b)), $(string(a)), $(string(b))))
1025-
end
1026-
export @test_approx_eq
1027-
10281004
_args_and_call(args...; kwargs...) = (args[1:end-1], kwargs, args[end](args[1:end-1]...; kwargs...))
10291005
"""
10301006
@inferred f(x)
@@ -1119,13 +1095,13 @@ end
11191095
# Raises an error if any columnwise vector norm exceeds err. Otherwise, returns
11201096
# nothing.
11211097
function test_approx_eq_modphase{S<:Real,T<:Real}(
1122-
a::StridedVecOrMat{S}, b::StridedVecOrMat{T}, err=nothing)
1098+
a::StridedVecOrMat{S}, b::StridedVecOrMat{T},
1099+
err = length(indices(a,1))^3*(eps(S)+eps(T))
1100+
)
11231101
@test indices(a,1) == indices(b,1) && indices(a,2) == indices(b,2)
1124-
m = length(indices(a,1))
1125-
err === nothing && (err=m^3*(eps(S)+eps(T)))
11261102
for i in indices(a,2)
11271103
v1, v2 = a[:, i], b[:, i]
1128-
@test_approx_eq_eps min(abs(norm(v1-v2)), abs(norm(v1+v2))) 0.0 err
1104+
@test min(abs(norm(v1-v2)),abs(norm(v1+v2))) 0.0 atol=err
11291105
end
11301106
end
11311107

test/complex.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ end
101101
@test exp(x) exp(big(x))
102102
@test exp10(x) exp10(big(x))
103103
@test exp2(x) exp2(big(x))
104-
@test_approx_eq_eps expm1(x) expm1(big(x)) eps(T)
104+
@test expm1(x) expm1(big(x)) atol=eps(T)
105105
@test log(x) log(big(x))
106106
@test log10(x) log10(big(x))
107107
@test log1p(x) log1p(big(x))

test/linalg/arnoldi.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ using Base.Test
3434
@test a*v[:,2] d[2]*v[:,2]
3535
@test norm(v) > testtol # eigenvectors cannot be null vectors
3636
# (d,v) = eigs(a, b, nev=3, tol=1e-8) # not handled yet
37-
# @test_approx_eq_eps a*v[:,2] d[2]*b*v[:,2] testtol
37+
# @test a*v[:,2] d[2]*b*v[:,2] atol=testtol
3838
# @test norm(v) > testtol # eigenvectors cannot be null vectors
3939

4040
(d,v) = eigs(asym, nev=3)
@@ -47,7 +47,7 @@ using Base.Test
4747
@test eigs(apd; nev=1, sigma=d[3])[1][1] d[3]
4848

4949
(d,v) = eigs(apd, bpd, nev=3, tol=1e-8)
50-
@test_approx_eq_eps apd*v[:,2] d[2]*bpd*v[:,2] testtol
50+
@test apd*v[:,2] d[2]*bpd*v[:,2] atol=testtol
5151
@test norm(v) > testtol # eigenvectors cannot be null vectors
5252

5353
@testset "(shift-and-)invert mode" begin
@@ -56,7 +56,7 @@ using Base.Test
5656
@test norm(v) > testtol # eigenvectors cannot be null vectors
5757

5858
(d,v) = eigs(apd, bpd, nev=3, sigma=0, tol=1e-8)
59-
@test_approx_eq_eps apd*v[:,1] d[1]*bpd*v[:,1] testtol
59+
@test apd*v[:,1] d[1]*bpd*v[:,1] atol=testtol
6060
@test norm(v) > testtol # eigenvectors cannot be null vectors
6161
end
6262

@@ -99,7 +99,7 @@ let A6965 = [
9999
# 0.8 0.1 0.1
100100
# 0.7 0.1 0.2 ]
101101
#d,v,nconv = eigs(T6965,nev=1,which=:LM)
102-
#@test_approx_eq_eps T6965*v d[1]*v 1e-6
102+
# @test T6965*v d[1]*v atol=1e-6
103103
end
104104

105105
# Example from Quantum Information Theory

test/linalg/bidiag.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ srand(1)
198198
Test.test_approx_eq_modphase(u1, u2)
199199
Test.test_approx_eq_modphase(v1, v2)
200200
end
201-
@test_approx_eq_eps 0 vecnorm(u2*diagm(d2)*v2'-Tfull) n*max(n^2*eps(relty), vecnorm(u1*diagm(d1)*v1' - Tfull))
201+
@test 0 vecnorm(u2*diagm(d2)*v2'-Tfull) atol=n*max(n^2*eps(relty),vecnorm(u1*diagm(d1)*v1'-Tfull))
202202
@inferred svdvals(T)
203203
@inferred svd(T)
204204
end

test/linalg/bunchkaufman.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ bimg = randn(n,2)/2
5757
@test logabsdet(bc1)[2] sign(det(bc1))
5858
end
5959
@test inv(bc1)*asym eye(n)
60-
@test_approx_eq_eps asym*(bc1\b) b 1000ε
60+
@test asym*(bc1\b) b atol=1000ε
6161
@testset for rook in (false, true)
6262
@test inv(bkfact(a.'+a, :U, true, rook))*(a.'+a) eye(n)
6363
@test size(bc1) == size(bc1.LD)
@@ -76,7 +76,7 @@ bimg = randn(n,2)/2
7676
@test logabsdet(bc2)[1] log(abs(det(bc2)))
7777
@test logabsdet(bc2)[2] == sign(det(bc2))
7878
@test inv(bc2)*apd eye(n)
79-
@test_approx_eq_eps apd * (bc2\b) b 150000ε
79+
@test apd*(bc2\b) b atol=150000ε
8080
@test ishermitian(bc2) == !issymmetric(bc2)
8181
end
8282
end

test/linalg/dense.jl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ for elty in (Float32, Float64, Complex64, Complex128)
2626
a = view(ainit, 1:n, 1:n)
2727
end
2828
# cond
29-
@test_approx_eq_eps cond(a, 1) 4.837320054554436e+02 0.01
30-
@test_approx_eq_eps cond(a, 2) 1.960057871514615e+02 0.01
31-
@test_approx_eq_eps cond(a, Inf) 3.757017682707787e+02 0.01
32-
@test_approx_eq_eps cond(a[:,1:5]) 10.233059337453463 0.01
29+
@test cond(a,1) 4.837320054554436e+02 atol=0.01
30+
@test cond(a,2) 1.960057871514615e+02 atol=0.01
31+
@test cond(a,Inf) 3.757017682707787e+02 atol=0.01
32+
@test cond(a[:,1:5]) 10.233059337453463 atol=0.01
3333
@test_throws ArgumentError cond(a,3)
3434
end
3535
end
@@ -75,8 +75,8 @@ debug && println("Solve square general system of equations")
7575
debug && println("Test nullspace")
7676
a15null = nullspace(a[:,1:n1]')
7777
@test rank([a[:,1:n1] a15null]) == 10
78-
@test_approx_eq_eps norm(a[:,1:n1]'a15null, Inf) zero(eltya) 300ε
79-
@test_approx_eq_eps norm(a15null'a[:,1:n1], Inf) zero(eltya) 400ε
78+
@test norm(a[:,1:n1]'a15null,Inf) zero(eltya) atol=300ε
79+
@test norm(a15null'a[:,1:n1],Inf) zero(eltya) atol=400ε
8080
@test size(nullspace(b), 2) == 0
8181
@test nullspace(zeros(eltya,n)) == eye(eltya,1)
8282
end

0 commit comments

Comments
 (0)