<- test(is.integer(x))
test_is_integer test_is_integer(10L) # TRUE
test_is_integer("A") # FALSE
checkwriter
Easily write, compose, and edit functions for testing and checking objects in R.
This is a copy of the README for my package {checkwriter}, which is currently under construction. You can follow the development of {checkwriter} here.
{checkwriter} is a package for writing and composing fast object tests and checks with Tidyverse-style-guide-compliant error messages. {checkwriter} provides the following core functions:
test()
, generate a test function which returnsTRUE
orFALSE
check()
, generate a check function which returns it’s input if that input passes atest()
and emits an error otherwiseand_checks()
, combine severalcheck()
functions using&&
. Inputs must pass everytest()
associated with the combinedcheck()
functionsor_checks()
, combine severalcheck()
functions using||
. Inputs must pass at least onetest()
associated with the combinedcheck()
functionsvectorize_check()
, convert a scalarcheck()
function to a vectorizedcheck()
Installation
You can install the development version of {checkwriter} from GitHub with:
# install.packages("devtools")
::install_github("EthanSansom/checkwriter") devtools
Features
These are mostly un-implemented as of yet. Shown below are un-run examples which showcase the {checkwriter} interface.
A <checkwriter_test>
is a function which returns TRUE
or FALSE
.
The first argument of a <checkwriter_test>
functions is always x
, the object to be tested. Other required test arguments can be supplied to ...
.
# Test whether `x` is length `len`. `null_or()` returns `NULL` if it's first
# argument is `NULL`. This means that, by default, `test_length(x)` always
# returns `TRUE`.
<- test(null_or(len, len == length(x)), len = NULL)
test_length
test_length(1:5) # TRUE
test_length(1:5, len = 5L) # TRUE
test_length(1:5, len = 2L) # FALSE
A <checkwriter_check>
is a function which returns its input if a test is passed and emits an error otherwise.
<- check(
check_is_integer test = test_is_integer,
header = "{.arg {x_name}} must be an integer.",
bullets = "{.arg {x_name}} is {.obj_type_friendly {x}}."
)
check_is_integer(10L)
#> [1] 10
try(check_is_integer("A"))
#> Error:
#> ! `"A"` must be an integer.
#> ✖ `"A"` is a string.
Note that we build up a check()
function using a test()
. The generated check inherits all of the arguments of its input test (e.g. len
). Additionally, check()
generates an argument arg_name = rlang::caller_arg(arg)
for each of it’s test arguments. These names can then be used in error messages.
<- check(
check_length .test = test_length,
.header = "{.arg {x_name}} must be length {len}.",
.bullets = "{.arg {x_name}} is length {length(x)}."
)
check_length(1:5, len = 5, x_name = "x")
#> [1] 1 2 3 4 5
try(check_length(1:5, len = 2L, x_name = "x"))
#> Error:
#> ! `x` must be length 2.
#> ✖ `x` is length 5.
Several checks can be composed with and_checks()
to make a new <checkwriter_check>
function. By default, checks composed using and_checks()
emit a message with the error bullets
associated with the first failed test (e.g. is.integer
or len == length(x)
).
<- and_checks(
check_int # If we're not checking the length `len` don't mention
# it in the error message.
.header = if_null_else(
len,"{.arg {x_name}} must be an integer.",
"{.arg {x_name}} must be an integer of length {len}."
),
check_is_integer,
check_length
)
check_int(10L, len = 1L)
#> [1] 10
try(check_int(c(1L, 2L), len = 5L, x_name = "x"))
#> Error:
#> ! `x` must be an integer of length 5.
#> ✖ `x` is length 2.
try(check_int("B"))
#> Error:
#> ! `"B"` must be an integer.
#> ✖ `"B"` is a string.