How to add a test to mrds.

Unit testing in mrds is provided by Hadley Wickham’s excellent testthat package. More information on testthat can be found on github.

Testing mrds

In mrds, tests are stored in mrds/inst/tests/. You can run these tests by either running:

R CMD CHECK mrds

on the command line, or within R:

library(testthat)
test_package("mrds")

Writing a new test

One can add a test by adding a new file in the directory mrds/inst/tests/. By convention test filenames start with test_ and are followed by a useful descriptor, ending in .R.

A simple test consists of running some code then checking the returned object was as expected. To show how the testing works we’ll build up something similar to test_easy.R.

First, as usual load some packages:

library(mrds)
library(testthat)

we can then load the golf tee data that is shipped with mrds:

data(book.tee.data)
egdata<-book.tee.data$book.tee.dataframe

and then fit a very simple model to the data:

result<-ddf(dsmodel = ~cds(key = "hn"),
                data = egdata, method = "ds", meta.data = list(width = 4))

Two obvious tests we might want are to check that the abundance estimate is the same as a value that we know to be correct. So we expect_that that the value equals the one we supplied:

expect_that(result$Nhat, equals(231.347,tolerance=1e-6))

again this is pretty straight forward. We can supply a tolerance that is appropriate to the quantity we’re testing (we might only care that abundance estimates are the same to the nearest whole animal, for example).

Running the above will print nothing to the screen, expect will only talk to you if something goes wrong, e.g.:

expect_that(result$Nhat, equals(1,tolerance=1e-6))
Error: result$Nhat not equal to 1
Mean relative difference: 230.347

There are other expectations one can have ?expect_that and the above guide from Hadley give some ideas of the options available. equals doesn’t test for absolute equality (hence the tolerance option).

There are two additional tools that can be used to add structure to the tests. The first is test_that, we can use test_that to group expect_thats together:

test_that("golf tee data gives the same results as Distance",{
  # test that the abundance is the same as distance
  expect_that(result$Nhat, equals(231.347,tolerance=1e-6))
  # test that the log-likelihood is the same
  expect_that(result$lnl, equals(-215.1466,tolerance=1e-6))
})

Finally, one can set a context, for a group of test_thats

context("easy tests!")

test_that("golf tee data gives the same results as Distance",{
  # test that the abundance is the same as distance
  expect_that(result$Nhat, equals(231.347,tolerance=1e-6))
  # test that the log-likelihood is the same
  expect_that(result$lnl, equals(-215.1466,tolerance=1e-6))
})

test_that("golf tee data - these will fail!",{
  # test that the abundance is the same as distance
  expect_that(result$Nhat, equals(2,tolerance=1e-6))
  # test that the log-likelihood is the same
  expect_that(result$lnl, equals(-1e20,tolerance=1e-6))
})

running the above will give the following result:

Error: Test failure in 'golf tee data - these will fail!'
* result$Nhat not equal to 2
Mean relative difference: 114.6735
* result$lnl not equal to -1e+20
Mean relative difference: 1

We can also save these tests into a file and run them using test_file, which might look like this:

library(mrds)
library(testthat)

data(book.tee.data)
egdata<-book.tee.data$book.tee.dataframe

result<-ddf(dsmodel = ~cds(key = "hn"),
                data = egdata, method = "ds", meta.data = list(width = 4))

context("easy tests!")

test_that("golf tee data gives the same results as Distance",{
  # test that the abundance is the same as distance
  expect_that(result$Nhat, equals(231.347,tolerance=1e-6))
  # test that the log-likelihood is the same
  expect_that(result$lnl, equals(-215.1466,tolerance=1e-6))
})

test_that("golf tee data - these will fail!",{
  # test that the abundance is the same as distance
  expect_that(result$Nhat, equals(2,tolerance=1e-6))
  # test that the log-likelihood is the same
  expect_that(result$lnl, equals(-1e20,tolerance=1e-6))
})

the results of running the test would be:

easy tests! : ..12


1. Failure: golf tee data - these will fail! -----------------------------------
result$Nhat not equal to 2
Mean relative difference: 114.6735

2. Failure: golf tee data - these will fail! -----------------------------------
result$lnl not equal to -1e+20
Mean relative difference: 1

As we can see, if the test runs then a . is printed to the screen. Otherwise, if the test fails, a number is printed and at the end the numbered errors are printed.