# Expect output of 7
add_two(5)Testing Package Code
The Art of Unit Tests
Would you get into an airplane that nobody had ever flown before? What if it had been flown, but only under perfect conditions - blue skies, no wind - but not in bad weather? What if it had only ever been flown with no passengers or cargo inside?
Just like with any other technology, when you build a new package, you need to test it out before you send it off to be used in real applications. The way to test out functions is by writing unit tests that make sure the function behaves how you expect - both in ideal settings, and when there is a problem!
Last week, you saw some examples of unit tests in the testthat package structure. For now, we’ll take a step back from that formal structure and simply think about how to write quick code to check your function.
Suppose you have a function called add_two that claims to add a two to any number. What might you want to try before you would trust this function?
Well, you’d probably want to try a very simple input to see if you believe it:
You also might want to double check if it works with decimals or only integers:
# Expect output of 7.5
add_two(5.5)You might want to see if it will give a helpful error when you input a non-number:
# Expect error
add_two("a")You might want to experiment to see if it is vectorized, or what other data types it works with.
# Expect either c(7, 8) or an error
add_two(c(5, 6))
test <- tibble(a = 5, b = 6)
# Expect either a tibble with a = 7, b = 8; or an error
add_two(test)Testing packages with testthat
testthat
- When you create testing code like:
test_that("the function bob works", {
expect_equal(bob(2), 4)
})What file should this code go in?
What folder(s) should that file live in?
What function in the blank below will create a well-named file in the correct place?
usethis::_____("bob")- Which
expect_function should you use when…
You want to check that values match, but not specific data types.
You want to check that outputs match, including the exact data type.
You want the code to produce an error.
Test Coverage
In open-source development, users must rely on and trust packages made by others.
Unit tests provide some level of reassurance that the package works, and will continue to work. A package with good testthat tests can be changed and updated with confidence, because you know that they are always making sure those original tests still pass.
It’s impossible to test every single thing someone might put into your function - this is why bugs still exist! - but the more coverage you include, the more stable your package will be.
The covr package provides measurements of how thoroughly your package is covered by your unit tests.
Open up your regexcite package project from last week. Then run
covr::package_coverage(".")What did this return? What is the coverage of your package?
covr
Which of the following is not a reason to have good test coverage in a package?
It helps other people trust that your package works as intended.
It helps you debug if you break something.
It gives users some examples of how your functions should be used.