tinytest icon indicating copy to clipboard operation
tinytest copied to clipboard

Feature suggestion: recursively test directories with `run_test_dir`

Open telegott opened this issue 1 year ago • 2 comments

There has been a lot of movement to make R code more modular, most recently with the box package, which supports Python-like imports and treats files as encapsulated modules. This allows for a much cleaner structure than a regular R package does, as now you can have as many nested directories in R/ as you want. A lot of shiny app frameworks like rhino also move into this direction, and a lot of best-practice talks at conferences recommend related approaches such as modules that promote more encapsulation than R can offer.

The downside is that so far I haven't found a clean approach that would support testing a structure like that, since always regular package structures are expected. I created a hacky solution using tinytest:

test_dir <- function(directory) {
  message('Testing directory ', directory)
  test <- tinytest::run_test_dir(directory)
  frame <- as.data.frame(test)
  frame$path <- paste(directory, frame$file, sep = "/")
  frame
}

clean_characters <- \(vec) gsub("\r?\n|\r", "", vec)

dirs <- list.dirs(path = "tests", full.names = TRUE, recursive = TRUE)
tests <- do.call(what = 'rbind', args = lapply(dirs, test_dir))

if (all(tests$result)) {
  message('All tests passed')
  quit(status = 0)
} else {
  failed_tests <- tests[!tests$result,]
  for (column in c('call', 'diff')) {
    failed_tests[[column]] <- clean_characters(failed_tests[[column]])
  }
  error_messages <- paste(
    failed_tests$path,
    paste0('lines: ', failed_tests$first, ':', failed_tests$last),
    paste0('call: ', failed_tests$call),
    paste0('error: ', failed_tests$diff),
    sep = ' | '
  )
  stop('\n', paste(error_messages, collapse = '\n'))
}

Would it be possible to support something like recurse = TRUE to run_test_dir out of the box or are there drawbacks to this? With an approach like this, it's not the test package's duty to somehow find the code that should be tested, each test file imports the code itself.

telegott avatar Sep 07 '22 21:09 telegott

I feel like this could be done. I have to see how easy it is. Also, as tinytest can run in parallel (with the file as unit for parallel running) I'd have to see if there are consequences there.

markvanderloo avatar Sep 08 '22 14:09 markvanderloo

Thanks for considering this, this would be a very helpful feature I think and make testing more accessible to people who do not use R package structures as umbrella for their work.

telegott avatar Sep 09 '22 08:09 telegott