Get startedGet started for free

Storing expectations as unit tests and running tests

1. Storing expectations as unit tests and running tests

Welcome back.

2. Workflow

The process for creating and testing unit tests usually follows five steps. First, we create examples for our users in R Markdown template files, vignettes, and the roxygen2 headings of our function help files. Second, we design more examples to use in expectations that verify if our function produces the expected output. Third, as we design expectations, we group them to form a unit test for a particular unit of our code. Fourth, we build out many different unit tests for a particular function in a single testing R script. Lastly, we can run all unit tests across the entire package. Note this can take some time to run for larger packages. Thus, it is recommended to run all tests on a file instead of running all tests throughout the package if we are working on a single function and its tests.

3. Grouping similar function expectations together

So far, we've seen how to create and use expectations to ensure our functions behave in the expected ways. We'll next explore how to organize these expectations together. We wrote expectations for various functions related to converting temperatures into different formats. We can group them into a unit test using testthat's test_that function. Its first argument is text that explains what the expectations are that follow. This will be outputted if expectations do not provide the expected output. The next argument gives the expectations to run surrounded by curly braces. Running this in R tells us that the test has passed.

4. What if tests failed?

If there are failures, corresponding messages provide guidance on the issues. This could mean that we've changed the code in our functions in some way so that they no longer work. Let's modify our expectation code to see what kinds of messages we get. The first output is from expect_equal testing if 32 Fahrenheit converts to 1. Despite expect_equal tolerating some error, this error is too large, so we get the output telling us it is not equal. Similarly, -40 Fahrenheit is not 0 Celsius within a reasonable tolerance. Lastly, 25 Fahrenheit has a Celsius temperature, so that does not give us an error.

5. Running all tests in a file

To streamline running multiple tests, we can place them in a single file and use the test_file function from the testthat package. This function takes the path to the test file as its main argument. Here we could store the tests in the test-temp_conversion-dot-R file in our package. This could be helpful if we have found that some new functionality only breaks code in the temperature conversions but not with the other conversion types in the package. Assuming we've made the fixes to our code to make the expectations work, we can expect output saying that conversions to and from the two temperature scales are working.

6. Run tests on the examples

We discussed creating examples above our functions using roxygen2 as given here for the temp_converter function. If we want to check that the examples given for converting temperatures produce the expected values, we can do so using the test_example function. Its argument is the path of the function help file in the man directory created after roxygenizing those examples we want to check. In this instance, we pass man-temp_converter-dot-Rd in quotes. As with test_that, the output given tells us if the tests passed with an emoji or if something failed.

7. You gotta run 'em all!

It is best practice to use test_file if we are building out functionality for a particular function stored in a test file. We don't need to run test_file on every individual file. This could be a daunting task if we have many functions in our package. Instead, we can use test_package to run tests across all the testing files in our package. The main argument to test_package is the package name we'd like to run all of the tests for. Just as test_that and test_file would give us any failing expectations, this will list from each file any errors and allow us to dig in further to get us back to all passing tests!

8. Let's practice!

Let's practice.