library(testthat) knitr::opts_chunk$set(collapse = TRUE, comment = "#>")
This vignette shows you how to create custom expectations that work identically to the built-in expect_ functions. Since these functions will need to be loaded in order for your tests to work, we recommend putting them in an appropriately named helper file, i.e. tests/testthat/helper-expectations.R.
There are three main parts to writing an expectation, as illustrated by expect_length():
expect_length <- function(object, n) { # 1. Capture object and label act <- quasi_label(rlang::enquo(object), arg = "object") # 2. Call expect() act$n <- length(act$val) expect( act$n == n, sprintf("%s has length %i, not length %i.", act$lab, act$n, n) ) # 3. Invisibly return the value invisible(act$val) }
The first step in any expectation is to capture the actual object, and generate a label for it to use if a failure occur. All testthat expectations support quasiquotation so that you can unquote variables. This makes it easier to generate good labels when the expectation is called from a function or within a for loop.
By convention, the first argument to every expect_ function is called object, and you capture it's value (val) and label (lab) with act <- quasi_label(enquo(object)), where act is short for actual.
Next, you should verify the expectation. This often involves a little computation (here just figuring out the length), and you should typically store the results back into the act object.
Next you call expect(). This has two arguments:
ok: was the expectation successful? This is usually easy to write
failure_message: What informative error message should be reported to
the user so that they can diagnose the problem. This is often hard to
write!
For historical reasons, most built-in expectations generate these with
sprintf(), but today I'd recommend using the
glue package
Expectation functions are called primarily for their side-effects (triggering a failure), so should invisibly return their input, act$val. This allows expectations to be chained:
mtcars %>% expect_type("list") %>% expect_s3_class("data.frame") %>% expect_length(11)
succeed() and fail()For expectations with more complex logic governing when success or failure occurs, you can use succeed() and fail(). These are simple wrappers around expect() that allow you to write code that looks like this:
expect_length <- function(object, n) { act <- quasi_label(rlang::enquo(object), arg = "object") act$n <- length(act$val) if (act$n == n) { succeed() return(invisible(act$val)) } message <- sprintf("%s has length %i, not length %i.", act$lab, act$n, n) fail(message) }
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.