Search code examples
rassertionsassertthat

Warnings instead of errors from assert_that()?


I'm using R's assertthat package and am wanting to (temporarily) output a warning instead of an error on assertion failure. What's the easiest way to do that with the assertthat package?

I realize that wanting warnings instead of errors kind of goes against what assertions are supposed to be used for. In the long term, we indeed want to be outputting errors on assertion failure. In the short term, we still want the code to function even with bad input, since the output with bad inputs is still "good enough" for now.

A simple example: suppose I have a function that takes x as input and outputs x+5. I want to output a warning if x!=3. Since we will be using assert_that ultimately, it would be nice if we can use assertthat package for the warning.

In the long term, we'll use this:

> x <- 3
> fn <- function(x) {assert_that(x==3); return(x+5)}
> fn(3)
[1] 8
> fn(4)
 Error: x not equal to 3 

In the short term, here's the best I have so far:

> fn <- function(x) {if(!see_if(x==3)) warning(validate_that(x==3)); return(x+5)}
> fn(3)
[1] 8
> fn(4)
[1] 9
Warning message:
In fn(4) : x not equal to 3

I'm looking for a more concise solution, if possible (best case would be passing an "output_warning" parameter to assert_that, but I don't think that exists).


Solution

  • I created a user defined function which accepts a string corresponding to an expression against which you would like to run validate_that() (ultimately assert_that()). The function prints a warning if the assertion fails and remains silent otherwise. See below for usage. You could easily extend this custom function to accept more than one expression if necessary. Note that I also use sys.calls() to obtain the name of the function which called this helper function. This is an important piece of information so you can correlate your warnings with the code that actually generated them.

    assert_that_soft <- function(exp) {
                            if (!exp) {
                                print (paste("Error in function:",
                                       parse(sys.calls()[[sys.nframe()-1]])) ) # name of caller
                            }
                        }
    

    Usage:

    > fn <- function(x) { assert_that_soft(x==3); return(x+5) }
    > fn(3)
    [1] 8
    > fn(8)
    [1] "Error in function: fn(8)"
    [1] 13