ut_cmp.Rd
A wrapper for all.equal
and identical
that provides
more useful diagnostics when used in a unittest ok
function.
First item to compare, usually the result of whatever you are testing
Second item to compare, usually the expected output of whatever you are testing
An optional filter function, that turns either a or b into text, and prints this out
Tell sys.call
which frame to deparse to get original expressions.
Set to -2
when making a helper function, see examples.
Number of lines of context surrounding changed lines to print.
Other arguments passed directly to all.equal
For both functions, a
and b
are first passed to
all.equal
(for ut_cmp_equal()
) or
identical
(for ut_cmp_identical()
). If they match, then
the function returns TRUE and your test passes.
If this fails, then we turn both a
and b
into text, and then
use git diff
to compare the 2 outputs. If you do not have git
installed, then the 2 outputs will be shown side-by-side.
When using git diff
, we turn colored output on when outputting to a
terminal. You can force this on or off using options("cli.num_colors" = 1)
or the NO_COLOR
or R_CLI_NUM_COLORS
environment variable.
The step of turning into text is done with the filter function. There are
several of these built-in, and it will choose the one that produces the
simplest output. This may mean that the output will be from the print
function if the differences are obvious, or str
with many
decimal places if there are subtle differences between the 2.
You can also provide your own filter function if there's a particular way
you would like to see the data when comparing, for example you can use
write.table
if your data is easiest to understand in tabular output.
Returns TRUE
if a
& b
are all.equal
(for ut_cmp_equal()
) or identical
(for ut_cmp_identical()
).
Otherwise, returns an invisible()
character vector of diagnostic
strings helping you find where the difference is.
If called directly in an interactive R session, this output will be printed to the console.
## A function to test:
fn <- function(x) { seq(x) }
## Get it right, and test passes:
ok(ut_cmp_equal(fn(3), c(1,2,3)))
#> ok - ut_cmp_equal(fn(3), c(1, 2, 3))
## Get it wrong, and we get told where in the output things are different:
ok(ut_cmp_equal(fn(3), c(1,4,3)))
#> not ok - ut_cmp_equal(fn(3), c(1, 4, 3))
#> # Test returned non-TRUE value:
#> # Mean relative difference: 1
#> # --- fn(3)
#> # +++ c(1, 4, 3)
#> # [1] 1 [-2-]{+4+} 3
## Using a custom filter, we can format the output with write.table:
ok(ut_cmp_equal(fn(3), c(1,4,3), filter = write.table))
#> not ok - ut_cmp_equal(fn(3), c(1, 4, 3), filter = write.table)
#> # Test returned non-TRUE value:
#> # Mean relative difference: 1
#> # --- fn(3)
#> # +++ c(1, 4, 3)
#> # "x"
#> # "1" 1
#> # "2" [-2-]{+4+}
#> # "3" 3
## With ut_cmp_equal, an integer 1 is the same as a numeric 1
ok(ut_cmp_equal(as.numeric(1), as.integer(1)))
#> ok - ut_cmp_equal(as.numeric(1), as.integer(1))
## With ut_cmp_identical, they're not
ok(ut_cmp_identical(as.numeric(1), as.integer(1)))
#> not ok - ut_cmp_identical(as.numeric(1), as.integer(1))
#> # Test returned non-TRUE value:
#> # --- as.numeric(1)
#> # +++ as.integer(1)
#> # [-num-]{+int+} 1
## all.equal() takes a tolerance parameter, for example:
all.equal(0.01, 0.02, tolerance = 0.1)
#> [1] TRUE
## ...we can also give this to to ut_cmp_equal if we want a very
## approximate comparison
ok(ut_cmp_equal(0.01, 0.02, tolerance = 0.1))
#> ok - ut_cmp_equal(0.01, 0.02, tolerance = 0.1)
## We can make a comparison function of our own, and use
## deparse_frame to show the right expression in diff output
cmp_noorder <- function (a, b) {
sortlist <- function (x) if (length(x) > 0) x[order(names(x))] else x
ut_cmp_identical(sortlist(a), sortlist(b), deparse_frame = -2)
}
ok(cmp_noorder(list(a=1, b=2), list(b=2, a=3)))
#> not ok - cmp_noorder(list(a = 1, b = 2), list(b = 2, a = 3))
#> # Test returned non-TRUE value:
#> # --- list(a = 1, b = 2)
#> # +++ list(b = 2, a = 3)
#> # $a
#> # [1] [-1-]{+3+}
#> #
#> # $b
#> # [1] 2