Use the ut_cmp_error
function. For example, here is a
function that will throw an error for a bad argument:
add_four <- function(x) {
if( ! is.numeric(x) ) stop("x must be numeric")
return( x+4 )
}
We can test the argument check like this:
ok(ut_cmp_error(add_four("a"), "must be numeric"), "add_four() argument not numeric throws error")
## ok - add_four() argument not numeric throws error
Use the ut_cmp_warning
function. For example, here is a
function that will issue a warning if an argument contains
NA
:
has_similar_mean <- function(x, y, tol = 0.5) {
if( any(is.na(x)) ) warning("x contains NAs", call. = FALSE)
if( any(is.na(y)) ) warning("y contains NAs", call. = FALSE)
return( isTRUE(all.equal(mean(x), mean(y), tolerance = tol)) )
}
We can test for a warning like this:
ok(ut_cmp_warning(has_similar_mean(c(1,2,3,4), c(1,NA,5)), "y contains NAs"), "has_similar_mean() NAs in y issues a warning")
## ok - has_similar_mean() NAs in y issues a warning
We can check for multiple distinct warnings
ok(ut_cmp_warning(has_similar_mean(c(NA,2,3,4), c(1,NA,5)), expected_regexp = c("x contains NAs", "y contains NAs"), expected_count = 2L),
"has_similar_mean() NAs in arguments issue warnings")
## ok - has_similar_mean() NAs in arguments issue warnings
Here we could use the same regexp to match both wrnings
ok(ut_cmp_warning(has_similar_mean(c(NA,2,3,4), c(1,NA,5)), "^[xy] contains NAs", expected_count = 2L),
"has_similar_mean() NAs in arguments issue warnings")
## ok - has_similar_mean() NAs in arguments issue warnings
Use ut_cmp_equal(...)
or
ut_cmp_identical(...)
as replacements for
all.equal(...)
and identical(...)
respectively:
a <- c(1,2,3)
b <- 1:3
ok(ut_cmp_equal(a,b), "a and b are equal")
## ok - a and b are equal
ut_cmp_identical
will make sure your objects are
identical, and is more useful when comparing e.g. a list of strings
which should be exactly the same.
ut_cmp_equal
will test for ‘near equality’, and is more
useful when comparing numeric values which may be slightly different due
to floating-point accuracy.
Either way, if your test fails you will get verbose output showing you how they differ, and if you have git installed the output will be coloured. For example:
> ok(ut_cmp_equal(c(1,2,3,4,5), c(1,8,8,4,5))) not ok - ut_cmp_equal(c(1, 2, 3, 4, 5), c(1, 8, 8, 4, 5)) # Test returned non-TRUE value: # Mean relative difference: 2.2 # --- c(1, 2, 3, 4, 5) # +++ c(1, 8, 8, 4, 5) # [1] 1 [-2 3-]{+8 8+} 4 5
When dealing with many unit tests in one file it can be useful to group related unit tests.
The ok_group()
function is used like this:
ok_group("Test addition", {
ok(1 + 1 == 2, "Can add 1")
ok(1 + 3 == 4, "Can add 3")
})
## # Test addition
## ok - Can add 1
## ok - Can add 3
ok_group("Test subtraction", {
ok(1 - 1 == 0, "Can subtract 1")
ok(1 - 3 == -2, "Can subtract 3")
})
## # Test subtraction
## ok - Can subtract 1
## ok - Can subtract 3
x You can use local()
to ensure that state is localized
within an ok_group
ok_group("Test adding integers", local({
x <- 1L; y <- 2L
ok(x + y == 3L, "Can add integer variables")
}))
## # Test adding integers
## ok - Can add integer variables
No. Sit down and have a cup of tea. Hopefully the feeling will go away.