I am trying to use unit test to test the equality of two arrays, wheres the following test:

`@test [2.36248e-314, 2.36248e-314] ≈ [0.0, 0.0]`

would fail. The two entries in the vector, if compared separately with the same method, would pass the equality test. Is there an extended unit test for equality for arrays in julia?

What do you mean here?

```
julia> 2.36248e-314 ≈ 0.0
false
```

There is (although as @kristoffer.carlsson pointed out, the two arguments are not \approx individually). You can see which method is being called for any function call in Julia with `@which`

:

```
julia> @which [2.36248e-314, 2.36248e-314] ≈ [0.0, 0.0]
isapprox(x::AbstractArray, y::AbstractArray) in Base.LinAlg at linalg/generic.jl:1297
julia> @which 2e-314 ≈ 0.0
isapprox(x::Number, y::Number) in Base at floatfuncs.jl:205
```

and you can open the relevant line in your editor with `@edit`

:

```
julia> @edit [2.36248e-314, 2.36248e-314] ≈ [0.0, 0.0]
```

To just test elementwise you could use dot syntax

```
julia> [1.0, 1e9] ≈ [0.0, 1e9]
true
julia> all([1.0, 1e9] .≈ [0.0, 1e9])
false
```

If you want to test that an array is approximately zero, you need to either pass an absolute tolerance (`atol`

keyword) to `isapprox`

(you can also do `@test x ≈ y atol=sometolerance`

in 0.7) or just test `norm(x) ≤ sometolerance`

.

Without an `atol`

keyword, `≈`

only tests that the *relative* error is small, and in particular that about half of the significant digits match. `2.36248e-314 ≈ 0.0`

is `false`

because *none* of the significant digits match.

The default `atol`

is zero because there is no sensible way to pick a nonzero default absolute tolerance without additional information. The problem is that the absolute tolerance depends on the overall scale (it is “dimensionful”): the result of `x ≈ y`

shouldn’t change if you change the units/scaling, e.g. if you multiply both `x`

and `y`

by `1e18`

.

(I feel like this is a FAQ …)

I am actually surprised by this. I tested with 0.9999999999 and 1, which returns true, so I thought there is some default tolerance for equality testing.

As Steven described, there exists a default relative tolerance.

Copying the docstring here:

```
isapprox(x, y; rtol::Real=sqrt(eps), atol::Real=0, nans::Bool=false, norm::Function)
Inexact equality comparison: true if norm(x-y) <= atol + rtol*max(norm(x), norm(y)). The default atol is zero and the default rtol depends on the types of x and y. The
keyword argument nans determines whether or not NaN values are considered equal (defaults to false).
```

Why didn’t `isapprox(x::AbstractArray, y::AbstractArray)`

disappear as part of the . broadcasting deprecations?

Because it does something different from the dotted version.

Similar reason why `*(::Matrix, ::Matrix)`

didn’t get removed.

I came across this thread after struggling to make sense out of tests for array elements. It might be worth explicating in the docs. It appears that `@test all(isapprox.(x, y, atol=0.05))`

is the correct syntax (I couldn’t find anything simpler). One problem is `@test isapprox(x, y, atol=0.05)`

passes with 2 elements per array and this could lead a person to construct the wrong tests in the more general case.

```
#Both pass
N = 2
x = fill(1.03, N)
y = fill(1.0, N)
@test all(isapprox.(x, y, atol=0.05))
@test isapprox(x, y, atol=0.05)
```

```
using Test
N = 5
x = fill(1.03, N)
y = fill(1.0, N)
# only the first passes
@test all(isapprox.(x, y, atol=0.05))
@test isapprox(x, y, atol=0.05)
```

As noted by Kristoffer Carlsson above,

```
isapprox(a, b)
```

compares under some norm determined by the arguments. It is different from

```
all(isapprox.(a, b))
```

It is really up to the user to select the best comparison — either one could be useful in some context.

It is important to note that a custom norm can be specified for `isapprox`

, which allows things like

```
@test a ≈ b norm = my_custom_norm
```

in tests. I frequently find this useful.

In particular, `isapprox(a, b, atol=1e-2)`

is checking whether `norm(a - b) ≤ 1e-2`

, where `norm`

is the default Euclidean norm. It sounds like what you want (or *think* you want) is the “infinity norm”. If you define `norminf(x) = maximum(abs, x)`

(or use `norm(x, Inf)`

from the `LinearAlgebra`

package), then you could employ the `norm=norminf`

keyword as @Tamas_Papp suggested.

However, more generally I would tend to recommend *not* using `atol`

in floating-point approximate-equality tests — a more common choice should be `rtol`

(**relative** tolerance). For example,

```
@test x ≈ y rtol=0.05
```

(equivalently, `isapprox(x, y, rtol=0.05)`

) tests whether `x`

and `y`

are within 5% of one another in the sense that `norm(x-y) ≤ rtol*max(norm(x), norm(y))`

. The reason to use a relative tolerance is that it is **scale-invariant** (“dimensionless”): multiplying both `x`

and `y`

by any factor (changing the “units”) will not require you to change the test. (Note in particular that this test will always pass when `x = 1.03y`

as in your example, for *any* finite `x`

and `y`

.)

Moreover, all of the rules of floating-point arithmetic are designed to preserve *relative* accuracy, not absolute accuracy. For example `x + y`

in floating point is guaranteed to give the exact result up to a relative tolerance of the machine precision `ε`

(`eps(Float64) = 2.220446049250313e-16`

in double precision), not including overflow. (If you perform multiple addition operations, however, these errors can accumulate.) So it is much easier to select a reasonable `rtol`

than `atol`

.

The `isapprox`

function has a default `rtol`

of `√ε`

, which means that it checks whether about half of the significant digits match. This is a good default for most floating-point unit tests — coarse enough that it won’t give false negatives due to accumulated roundoff errors, but fine enough to catch most bugs that give the wrong answer (as opposed to bugs that simply exacerbate roundoff). Because of that, most floating-point unit tests can simply do `@test x ≈ y`

.

I’ve found the

```
norminf(x) = maximum(abs, x)
@test x ≈ y rtol = 0.01 norm = norminf
```

approach to work well, and fail with a clearer error message than the

```
@test all(isapprox.(x, y, rtol = 0.01))
```

approach. Could it be made so that

```
@test x .≈ y rtol = 0.01
```

is equivalent to the norminf approach? This seems fairly intuitive to me. Currently the above line fails with error

```
Expression evaluated to non-Boolean
Expression: .≈(x, y, atol = 0.01)
Value: Bool[1, 1]
```

Note that these tests are *not* mathematically equivalent.

Consider `x = [1,0]`

and `y = [1,1e-6]`

, in which case your first test passes while your second test fails. The first test is checking \Vert x - y \Vert_\infty \le 0.01 \max \{ \Vert x \Vert_\infty, \Vert y \Vert_\infty \} (which is `true`

), while the second test is checking |1 - 1| \le 0.01 \max \{ |1|, |1| \} (which is `true`

) *and* |0 - 10^{-6}| \le 0.01 \max \{ |0|, |10^{-6}| \} (which is `false`

) *separately*.

This *could* be done (because `@test`

is a macro and can rewrite any valid syntax arbitrarily) but I don’t think it *should* be done, because `.≈`

suggests an elementwise `isapprox.(...)`

call, which is *not* the same as `isapprox`

with an infinity norm as noted above.

Ok, makes sense