testthat Test File to a unitizerConverts a copy of an existing testthat test file to a
unitizer test file and test store, or a directory of such files to
a corresponding unitizer directory. See examples.
testthat_translate_file(file.name, target.dir = file.path(dirname(file.name),
"..", "unitizer"), state = getOption("unitizer.state"),
keep.testthat.call = TRUE, prompt = "always",
interactive.mode = interactive(), ...)testthat_translate_dir(dir.name, target.dir = file.path(dir.name, "..",
"unitizer"), filter = "^test.*\\.[rR]",
state = getOption("unitizer.state"), keep.testthat.call = TRUE,
force = FALSE, interactive.mode = interactive(), ...)
testthat_translate_name(file.name, target.dir = file.path(dirname(file.name),
"..", "unitizer"), name.new = NULL,
name.pattern = "^(?:test\\W*)?(.*)(?:\\.[rR])$",
name.replace = "\\1")
a path to the testthat test file to convert
the directory to create the unitizer test file and
test store in; for testthat_translate_file only: if NULL will return
as a character vector what the contents of the translated file would have
been instead of writing the file
what state control to use (see same argument for
unitize)
whether to preserve the testthat call that
was converted, as a comment
character(1L):
"always" to always prompt before writing new files
"overwrite" only prompt if existing file is about to be overwritten
"never" never prompt
logical(1L) primarily for testing purposes, allows
us to force prompting in non-interactive mode; note that unitize
and unitize_dir are always called in non-interactive mode by these
functions, this parameter only controls prompts generated directly by these
functions.
params to pass on to testthat_translate_name
a path to the testthat directory to convert
regular expression to select what files in a director are translated
logical(1L) whether to allow writing to a target.dir that
contains files (implies prompt="never" when
testthat_translate_dir runs testthat_translate_file)
character(1L) the base name for the unitizer files;
do not include an extension as we will add it (".R" for the testfile,
".unitizer" for the data directory); set to NULL to generate the name
from the testthat file name
character(1L) a regular expression intended to match
the testthat test file name (see name.replace) if
name.pattern matches, then the new file name will be
constructed with this (used as replace parameter to
sub); in addition we will add ".R" and ".unitizer" as the
extensions for the new files so do not include extensions in your
name.replace parameter
character(1L) the replacement token, typically would
include a "\1" token that is filled in by the match group from
name.pattern
a file path or a character vector (see target.dir)
If you already have an extensive test suite in testthat and you do not
intend to modify your tests or code very much there is little benefit (and
likely some drawbacks) to migrating your tests to unitizer. Please
see the introduction vignette for a (biased) view of the pros and cons of
unitizer relative to testthat.
These translation functions are provided for your convenience. The
unitizer author does not use them very much since he seldom needs to
migrate testthat tests. As a result, they have not been tested as
thoroughly as the rest of unitizer. Translation is designed to work
for the most common testthat use cases, but may not for yours. Make
sure you review the resulting unitizers to make sure
they contain what you expect before you start relying on them. This is
particularly important if your testthat test files are not meant to
be run stand-alone with just test_file (see "Differences That May
Cause Problems").
Note you can also unitize your testthat files without
translating them (see notes).
Start a fresh R session
Run your testthat tests with test_dir to
ensure they are still passing. If your tests are are runnable only
via test_check because they directly access the namespace of your
package, see "Differences That May Cause Problems" below
Run testthat_dir_translate
[optional] use review to review the resulting
unitizer(s)
We recommend using testthat_translate_dir over
testthat_translate_file because the former also copies and loads any
helper files that may be defined. Since libraries used by multiple test
files are commonly loaded in these helper files, it is likely that just
translating a single file without also copying the helper files will not
work properly.
We start by identifying calls to exported testthat functions
that have an object argument. Generally speaking this includes
functions of the form expect_* (e.g. expect_equal). We then
extract the object parameter and replace the original expect_*
statement with just the object parameter. For example
expect_equal(my_fun(25), 1:10)
becomes
my_fun(25)
Not all expect_* functions are substituted. For example,
expect_is and expect_that are left unchanged because the tests
for those functions do not or might not actually test the values of
object. For example, expect_is tests the class of
object. It is perfectly fine to unitize an expect_*
call unsubstituted. unitizer captures conditions, values, etc., so if
an expect_* test starts failing, it will be detected.
unitizer will then evaluate and store the results of such expressions.
Since in theory we just checked our testthat tests were working,
presumably the re-evaluated expressions will produce the same values. Please
note that the translation process does not actually check this is true (see
"Differences That May Cause Problems") so reviewing the results is a
good idea.
test_that calls are converted to unitizer_sect calls,
and the contents thereof are processed as described above. Calls to
context are commented out since there currently is no unitizer
equivalent. Other testthat calls are left unchanged and their return
values used as part of the unitizer tests.
Only top level calls are converted. For example, code like
for(i in 1:10) expect_equal(my_fun(i), seq(i)) or even
(expect_equal(my_fun(10), 1:10)) will not be converted since
expect_equal is nested inside a for and ( respectively.
You will need to manually edit these calls (or just let them remain as is,
which is not an issue).
We identify calls to extract based purely on the function symbols (i.e. we
do not check whether expect_equal actually resolves to
testthat::expect_equal in the context of the test file).
The unitizer files will be created in a sibling folder to the folder
containing the testthat files. The names of the new files will be
based on the old files. See params target.dir, name.new,
name.pattern, and name.replace for more details. We encourage
you to try the default settings first as those should work well in most
cases.
When using testthat_translate_dir, any files that match
"^helper.*[rR]$" are copied over to a '/_pre' subdirectory
in "target.dir", and are pre-loaded by default before the tests are
unitized.
If you run your tests during development with test_dir odds
are the translation will work just fine. On the other hand, if you rely
exclusively on test_check you may need to use
state=unitizerStateNoOpt(par.env="pkgName") when you translate to
make sure your tests have access to the internal namespace functions.
See unitizerState for details on how to modify state tracking.
If your tests were translated with the state parameter changed from
its default value, you will have to use the same value for that parameter in
future unitize or unitize_dir runs.
# NOT RUN {
library(testthat) # required
testthat_translate_file("tests/testthat/test-random.R")
# Translate `dplyr` tests (assumes `dplyr` source is in './dplyr')
# Normally we would use default `state` value but we cannot in this case
# due to conflicting packages and setup
testthat_translate_dir(
"dplyr/tests/testthat", state=unitizerStateSafe(par.env="dplyr")
)
# Make sure translation worked (checking one file here)
# *NOTE*: folder we are looking at has changed
review("dplyr/tests/unitizer/summarise.unitizer")
# Now we can unitize any time we change our code
unitize_dir(
"dplyr/tests/unitizer", state=unitizerStateSafe(par.env="dplyr")
)
# }
Run the code above in your browser using DataLab