Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

validatr

The goal of validatr is to contain validation functions re-used across FRAMverse packages. This is intended for internal use only.

Installation

You can install the development version of validatr from GitHub with:

# install.packages("pak")
pak::pak("FRAMverse/validatr")

validatr_error class of error messages

Under the hood, the validation functions in validatr use a special wrapper for cli::cli_abort()validation_abort() – that adds an error class of “validatr_error” to the error message. Error messages can be accessed with the rlang::catch_cnd() function:

library(cli)
#> Warning: package 'cli' was built under R version 4.4.3
library(validatr)

normal_cli_error <- rlang::catch_cnd(
  cli_abort("Normal error message!")
  )
class(normal_cli_error)
#> [1] "rlang_error" "error"       "condition"

framverse_cli_error <- rlang::catch_cnd(
  framverse_abort("Framverse error!")
)
class(framverse_cli_error)
#> [1] "simpleError" "error"       "condition"

This is done to improve handling of unit and integration tests with the testthat package. It allows us to use expect_error() and not have false positives when something else in the function errors.

As an example: imagine we have a poorly written function foo that is intended to take a character, validate the character, sleep for a specified duration, and print the value to the console. Imagine we also forgot to include the validate_character() function (here we represent is as commented out).

foo <- function(x, delay){
  # validate_character(x)
  Sys.sleep(delay - 100)
  print(x)
}

As we’re writing unit tests, we start by writing tests of the input validations. Does this function error when we provide a logical instead of a character? Well, if our test causes an error elsewhere in the function (e.g., by providing a value of delay that causes Sys.sleep to be called on a negative number), our test will appear to be successful even though we’re not actually doing input validation.

testthat::expect_error(foo(10, delay = 50))

even though the test would throw an error if we didn’t have another problem cropping up with our function call (since the only reason we errored was that our delay value was < 100):

testthat::expect_error(foo(10, delay = 101))
#> [1] 10
#> Error: Expected `foo(10, delay = 101)` to throw a error.

We can clarify this by setting the expectation for the class of error that pops up.

testthat::expect_error(foo(10, delay = 50),
                       class = "validatr_error")
#> Error: `foo(10, delay = 50)` threw an error with unexpected class.
#> Expected class: validatr_error
#> Actual class:   simpleError/error/condition
#> Message:        invalid 'time' value

The test will only be successful if we get the correct error. Let’s see that this works using a fixed version of our function, foo_2()

foo_2 <- function(x, delay){
  validate_character(x)
  Sys.sleep(delay - 100)
  print(x)
}
testthat::expect_error(foo_2(10, delay = 50),
                       class = "validatr_error")

Dev notes:

I am not intending for this to store validation functions that are only needed for a single, specific package. For example, there are a suite of validation functions for working with FRAM databases (e.g., confirm an input is a fram database, confirm that a stock id input is present in the FRAM database). Those will not be included in this package, as any functions that work with FRAM databases will either be in framrsquared or will be using framrsquared functions that will do the validation (e.g., functions in the framqaqc package).Similarly, there are some custom validation functions in the VizSeasonalGams package that are package-specific and will not be added here.

About

One Stop Shop For Validation Functions

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages