1

I want to test a function that can throw an error but I also want to ensure that a variable value is correct (to verify the expected last state before the error - so I want to test for unwanted side effects). Is it possible to do this?

Simplified expression to be tested

x <- 1    # could also be made "global" by "<<-"
stop("damn, an error occured")

How can I do something like

testthat("double check",
  expect_error_and_TRUE( x == 1, {
                                   x <- 1
                                   stop("damn, an error occured")
                                 }))

I could not find a way to "stack" (pipe) the expect functions?

R Yoda
  • 8,358
  • 2
  • 50
  • 87
  • First idea: https://stackoverflow.com/questions/4948361/how-do-i-save-warnings-and-errors-as-output-from-a-function/4952908#4952908 offers a wrapper function whose output could be for testing the expected values then. – R Yoda Nov 20 '16 at 10:52

2 Answers2

3

If a function returns a value it doesn't throws an error and otherwise round. You can test for a specific string in expect_error if you wish, so you could set in the error the value of x.

{
    x <- 1
    stop("damn, an error occured")
}
## Error: damn, an error occured
x
## [1] 1
rm(x)
f <- function(){
    x <- 1
    stop("damn, an error occured")
}
f() == 1
## Error in f() : damn, an error occured
expect_error(f(), "damn, an error occured")

f <- function(){
    x <- 1
    stop("damn, an error occured, x is ", x)
}
expect_error(f(), "x is 1")

I would advise against testing code outside a function, as it depends on the environment, where it is run, so if you run it in the testing file it might not be the same as in the "main" part of your code

llrs
  • 3,308
  • 35
  • 68
  • Thx for the details, this does work if I can and want modify the error message to show function internal "states". I think I should clarify my question: I do not want to test for the return value but for a side effect of the function which I do not want to show in the error message (yes, a very theoretical case). Since I did not write this in question I accept your answer. Thx again! – R Yoda Mar 01 '17 at 09:18
  • 1
    Depending on the side effect of the function (which usually *ones need to avoid* except for plotting and global configurations) you can look for testing a function for plotting. – llrs Mar 01 '17 at 09:40
  • 1
    I agree, testing a side effect is not the usual way you do it in unit tests (instead you treat the function as a black box unit). – R Yoda Mar 01 '17 at 09:50
0

Here is a better example now to test for an unwanted side effect - and a simple solution:

library(testthat)

counter <- 1

test_that("error occurs but does not change the previous value", {

  expect_error(if (log("a") == 42) counter <- counter + 1)
  expect_equal(counter, 1)

})
R Yoda
  • 8,358
  • 2
  • 50
  • 87