unitize: Unitize an R Test Script

View source: R/unitize.R

unitizeR Documentation

Unitize an R Test Script

Description

Turn standard R scripts into unit tests by storing the expressions therein along with the results of their evaluation, and provides an interactive prompt to review tests.

Usage

unitize(
  test.file = NULL,
  store.id = NULL,
  state = getOption("unitizer.state"),
  pre = NULL,
  post = NULL,
  history = getOption("unitizer.history.file"),
  interactive.mode = interactive(),
  force.update = FALSE,
  auto.accept = character(0L),
  use.diff = getOption("unitizer.use.diff"),
  show.progress = getOption("unitizer.show.progress", TRUE),
  transcript = getOption("unitizer.transcript", !interactive.mode)
)

review(
  store.id = NULL,
  use.diff = getOption("unitizer.use.diff"),
  show.progress = getOption("unitizer.show.progress", TRUE)
)

unitize_dir(
  test.dir = NULL,
  store.ids = filename_to_storeid,
  pattern = "^[^.].*\\.[Rr]$",
  state = getOption("unitizer.state"),
  pre = NULL,
  post = NULL,
  history = getOption("unitizer.history.file"),
  interactive.mode = interactive(),
  force.update = FALSE,
  auto.accept = character(0L),
  use.diff = getOption("unitizer.use.diff"),
  show.progress = getOption("unitizer.show.progress", TRUE),
  transcript = getOption("unitizer.transcript", !interactive.mode)
)

Arguments

test.file

path to the file containing tests, if supplied path does not match an actual system path, unitizer will try to infer a possible path. If NULL, will look for a file in the “tests/unitizer” package folder if it exists, or in “.” if it does not. See infer_unitizer_location) for details.

store.id

if NULL (default), unitizer will select a directory based on the test.file name by replacing .[rR] with .unitizer. You can also specify a directory name, or pass any object that has a defined get_unitizer method which allows you to specify non-standard unitizer storage mechanisms (see get_unitizer). Finally, you can pass an actual unitizer object if you are using review; see store.ids for unitize_dir

state

character(1L) one of c("prisitine", "suggested", "basic", "off", "safe"), an environment, or a state object produced by state or in_pkg; modifies how unitizer manages aspects of session state that could affect test evaluation, including the parent evaluation environment. For more details see unitizerState documentation and vignette("unitizer_reproducible_tests")

pre

NULL, or a character vector pointing to files and/or directories. If a character vector, then any files referenced therein will be sourced, and any directories referenced therein will be scanned non-recursively for visible files ending in ".r" or ".R", which are then also sourced. If NULL, then unitizer will look for a directory named "_pre" in the directory containing the first test file and will treat it as if you had specified it in pre. Any objects created by those scripts will be put into a parent environment for all tests. This provides a mechanism for creating objects that are shared across different test files, as well as loading shared packages. Unlike objects created during test evaluation, any objects created here will not be stored in the unitizer so you will have not direct way to check whether these objects changed across unitizer runs. Additionally, typing ls from the review prompt will not list these objects.

post

NULL, or a character vector pointing to files and/or directories. See pre. If NULL will look for a directory named "_post" in the directory containing the first test file. Scripts are run just prior to exiting unitizer. post code will be run in an environment with the environment used to run pre as the parent. This means that any objects created in pre will be available to post, which you can use to your advantage if there are some things you do in pre you wish to undo in post. Keep in mind that unitizer can manage most aspects of global state, so you should not need to use this parameter to unload packages, remove objects, etc. See details.

history

character(1L) path to file to use to store history generated during interactive unitizer session; the default is an empty string, which leads to unitizer using a temporary file, set to NULL to disable history capture.

interactive.mode

logical(1L) whether to run in interactive mode ( request user input when needed) or not (error if user input is required, e.g. if all tests do not pass).

force.update

logical(1L) if TRUE will give the option to re-store a unitizer after re-evaluating all the tests even if all tests passed. You can also toggle this option from the unitizer prompt by typing O (capital letter "o"), though force.update=TRUE will force update irrespective of whether you type O at the prompt

auto.accept

character(X) ADVANCED USE ONLY: YOU CAN EASILY DESTROY YOUR unitizer WITH THIS; whether to auto-accept tests without prompting, use values in c("new", "failed", "deleted", "error") to specify which type(s) of test you wish to auto accept (i.e. same as typing "Y" at the unitizer prompt) or empty character vector to turn off (default)

use.diff

TRUE or FALSE, whether to use diffs when there is an error, if FALSE uses all.equal instead.

show.progress

TRUE or FALSE or integer(1L) in 0:3, whether to show progress updates for each part of the process (TRUE or > 0), for each file processed (TRUE or > 1), and for each test processed (TRUE or > 2).

transcript

TRUE (default in non-interactive mode) or FALSE (default in interactive mode) causes immediate output of stdout/stderr during test evaluation instead of deferred display during test review. This also causes progress updates to display on new lines instead of overlaying on the same line. One limitation of running in this mode is that stderr is no longer captured at all so is unavailable in the review stage. stderr text that is also part of a signalled condition (e.g. "boom" in 'stop("boom")') is still shown with the conditions in the review step. To see direct stderr output in transcript mode scroll up to the test evaluation point.

test.dir

the directory to run the tests on; if NULL will use the “tests/unitizer” package folder if it exists, or “.” if it does not. See infer_unitizer_location) for details.

store.ids

one of

  • a function that converts test file names to unitizer ids; if unitizeing multiple files will be lapplyed over each file

  • a character vector with unitizer ids, must be the same length as the number of test files being reviewed (see store.id)

  • a list of unitizer ids, must be the same length as the number of test files being reviewed; useful when you implement special storage mechanisms for the unitizers (see get_unitizer)

pattern

a regular expression used to match what subset of files in test.dir to unitize

Details

unitize creates unit tests from a single R file, and unitize_dir creates tests from all the R files in the specified directory (analogous to testthat::test_dir).

unitizer stores are identified by unitizer ids, which by default are character strings containing the location of the folder the unitizer RDS files are kept in. unitize and friends will create a unitizer id for you based on the test file name and location, but you can specify your own location as an id, or even use a completely different mechanism to store the unitizer data by implementing S3 methods for get_unitizer and set_unitizer. For more details about storage see those functions.

review allows you to review existing unitizers and modify them by dropping tests from them. Tests are not evaluated in this mode; you are just allowed to review the results of previous evaluations of the tests Because of this, no effort is made to create reproducible state in the browsing environments, unlike with unitize or unitize_dir (see state parameter).

You are strongly encouraged to read through the vignettes for details and examples (browseVignettes("unitizer")). The demo (demo("unitizer")) is also a good introduction to these functions.

Value

unitize and company are intended to be used primarily for the interactive environment and side effects. The functions do return summary data about test outcomes and user input as unitizer_result objects, or for unitize_dir as unitizer_results objects, invisibly. See unitizer_result.

Note

unitizer approximates the semantics of sourcing an R file when running tests, and those of the interactive prompt when reviewing them. The semantics are not identical, and in some cases you may notice differences. For example, when running tests:

  • All expressions are run with options(warn=1), irrespective of what the user sets that option to.

  • on.exit(...) expressions will be evaluated immediately for top-level statements (either in the test file or in an unitizer_sect, thereby defeating their purpose).

  • Each test expression is run in its own environment, which is enclosed by that of previous tests.

  • Output and Message streams are sunk so any attempt to debug directly will be near-impossible as you won't see anything.

  • For portable tests it is best to use ASCII only string literals (avoiding even escaped bytes or Unicode characters), round numbers, etc., because unitizer uses deparsed test expressions as indices to retrieve reference values. See vignette('u1_intro', package='unitizer') for details and work-arounds.

When reviewing them:

  • ls() and q() are over-ridden by unitizer utility functions.

  • Expressions are evaluated with options(warn=1) or greater, although unlike in test running it is possible to set and keep options(warn=2).

  • Some single upper case letters will be interpreted as unitizer meta-commands.

For a more complete discussion of these differences see the introductory vignette (vignette('u1_intro')), the "Special Semantics" section of the tests vignette (vignette('u2_tests')), and the "Evaluating Expressions at the unitizer Prompt" section of the interactive environment vignette (vignette('u3_interactive-env')).

Default Settings

Many of the default settings are specified in the form getOption("...") to allow the user to "permanently" set them to their preferred modes by setting options in their .Rprofile file.

See Also

unitizerState, unitizer.opts, get_unitizer, infer_unitizer_location, unitizer_result


unitizer documentation built on Oct. 8, 2023, 5:06 p.m.