Search code examples
rdevtoolsr-packagetestthat

Where do I specify random seed for tests in R package?


I am using testthat to write tests for my R package. One of my tests makes use of jitter. I want to make sure the test is reproducible.

Do I put set.seed(1014)

  1. Before or after library(testthat) in ./tests/testthat.R; or
  2. At the top of each test file (before or after context("Test) in ./tests/testthat/test-function.R; or
  3. At the top of each unit test (inside of test_that("Example works"){jitter(1)})) in ./tests/testthat/test-function.R?

And why?


Solution

  • If you only declare set.seed() once, then you always need to run the tests that use randomness in the same order in order to get the same results. However, it's probably not a good idea for unit test to only work when run in a certain order. You should set the seed as close to the time that you need to verify a random value is returned.

    Here's a function that can set the seed for just a code block

    with_seed <- function(seed, code) {
      code <- substitute(code)
      orig.seed <- .Random.seed
      on.exit(.Random.seed <<- orig.seed)
      set.seed(seed)
      eval.parent(code)
    }
    

    You can run it like

    with_seed(5, rnorm(5))
    

    or

    with_seed(5, {
      a <- rnorm(5)
      b <- runif(5)
      a + b
    })
    

    But you will still get random numbers for the original seed outside the block.

    If you would prefer to pull such a function from an existing package, the withr::set_seed appears to do the same thing.