Hi, this is Sharon Machlis, Director of Editorial Data & Analytics at IDG Communications. I’m here with episode 3 of Do More With R: Test That Code With testthat.
So, uou’ve written a function. You run the function on a few different values, you get the results you want, you’re happy.
But then you need to make a change, so need to run the function again on all those different values, to make sure you didn’t break anything. With more than one or two test values and code changes, it can get annoying pretty fast.
That’s where the testthat package comes in. Its creator, Hadley Wickham, says testthat “tries to make testing as fun as possible, so that you get a visceral satisfaction from writing tests.” Honestly, I’m not sure if I’ll ever find testing code fun. But, testthat does make it pretty painless – and a lot better than one-off manual checks.
Let me show you how it works.
I’m going to create a simple function that finds “the first day of last month” from a character string input in year-month-day format.
Here’s the first version of the function:
I’ll load the function, and try it out a few times. All looks good! However, you may already see the problem. if I run this:
You see that the function doesn’t work for January.
I’ll need to re-do the function and test again. But instead of running all these tests manually, I’ll use testthat.
This is the format for a testthat test. The test_underscore_that function takes two arguments. The first argument is a description of the test. That’s important if you’re running a lot of different tests on a complex R package. It’s followed by a comma, because it’s the first of 2 arguments in the function.
The second argument is the actual comparisons between what your code does and what it should be doing. There are a lot of different testing options besides expect_equal. There’s expect_true, expect_length, expect_less_than … Type expect underscore when the testthat package is loaded, and you’ll see a lot of options. There’s even a way to write your own, custom expect conditions.
For this example, though, I just need expect equal.
So let’s write a test for the first_of_last_month function and see what happens.
You see here I’m checking dates in June and December. I expect the result for June 5 to be May 1, and December 1 to be November 1.
I’ll run that.
Nothing seems to be happening. That’s what you want in a test: Nice and quiet. What it’s really doing is returning a value of TRUE.
Now let’s add January to the test.
You can see the first line of the second argument tests the expectation that first_of_last_month for January 7, 2018 will equal December 1, 2017. We’ll run the test
And you see the test failed: the first of last month for January 7 didn’t equal December 1. And it shows the problem.
By the way, this isn’t like most coding in R. Usually in R, if there’s an error, the code stops running. test_that will still run all the tests, even after one fails. I’ll add another January test so you can see:
Now I’ll try a kind of complex version of the function using just base R, avoiding any package dependencies, and run my tests:
There’s a much easier way to do this function using the lubridate package, by the way, but meanwhile, let me check this version. I’ll source the test file
All quiet. Finally, here’s a version using lubridate.
I’ll load that version of the function and run the test.
Oh, there’s a problem. My result is a Date, when the target value is supposed to be a character string. So they’re not equal. Let me add as.character to the result and try again.
That does it.
And that’s all for this episode, thanks for watching! For more R tips, head to the More With R video page at bit.ly/morewithR. That’s https B I T period L Y slash more with R, all lowercase except for the R. So long!