R/Test
Overview
Suppose you've written a function in R. You want to make sure it works, so you try it with some sample data. By saving that information as a test case, you can re-run it again later if you ever need to change the function (for example, to make it run faster, or fix a case you hadn't thought of before). RUnit is a package that makes this easy. It's an xUnit style framework (don't worry if you don't know what that means). You can find a nice introduction to RUnit here.
Another unit-testing package is testthat, which is written by the famous Hadley Wickham. It's new and I (Gregor) haven't tried it yet, but given Hadley's other work (ggplot2, plyr) it's probably pretty darn good.
Step-by-Step
Here's the quick summary of what you need to do:
- Install RUnit from CRAN
- Create a file for the tests named runit.yourfilename.R (the important thing is that it start with "runit", though that is configurable)
- Create test functions that start with "test" (also configurable)
- Add tests using the checkEquals() and checkException() functions
- Run the tests as follows (you can also save to a file):
library( RUnit ) testsuite = defineTestSuite( "name", dirs="directory where your test files are" ) printTextProtocol( runTestSuite( testsuite ) )
Example
Let's use a function that calculates exponential population growth as an example. Suppose it's saved in a file called model.R. Here's the function:
calculatePopulation = function( initialSize, rate, time ) { if ( initialSize < 0 ) stop( "initial size must be positive") return( initialSize * exp( rate * time ) ) }
Here's an example runit.model.R file:
test.computePopulation = function() { checkEquals( calculatePopulation( 1000, 0.2, 0 ), 1000, "time 0") checkEquals( calculatePopulation( 1000, 0.2, 10 ), 7389.056, "time 10") checkEquals( calculatePopulation( 1000, -0.2, 10 ), 135, "negative rate", tolerance = 1 ) checkException( calculatePopulation( -1000, 0.2, 100 ), "negative initial size" ) }
The checkEquals() function takes the actual output from your function and compares it to the expected result you provide. You can also provide a message, which helps keep track of what you're testing. The checkException() function let's you check for expected errors.