This vignette shows you how to create custom expectations that work identically to the built-in expect_ functions.

## Creating an expectation

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))

# 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)
}

## Quasi-labelling

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 supporting 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.

### Verify the expectation

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:

1. ok: was the expectation successful? This is usually easy to write

2. 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

### Invisibly return the input

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)

## Testing your expectations

Use the expectations expect_success() and expect_failure() to test your expectation.


test_that("length computed correctly", {
expect_success(expect_length(1, 1))
expect_failure(expect_length(1, 2), "has length 1, not length 2.")
expect_success(expect_length(1:10, 10))
expect_success(expect_length(letters[1:5], 5))
})