% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/state.R
\name{unitizerState}
\alias{unitizerState}
\alias{state}
\alias{state,}
\alias{in_pkg}
\title{Tests and Session State}
\usage{
state(
  par.env,
  search.path,
  options,
  working.directory,
  random.seed,
  namespaces
)

in_pkg(package = NULL)
}
\arguments{
\item{par.env}{\code{NULL} to use the special \code{unitizer} parent
environment, or an environment to use as the parent environment, or
the name of a package as a character string to use that packages'
namespace as the parent environment, or a \code{unitizerInPkg} object
as produced by \code{\link{in_pkg}}, assumes .GlobalEnv if unspecified}

\item{search.path}{one of \code{0:2}, uses the default value corresponding to
\code{getOption(unitizer.state)}, which is 0 in the default unitizer state
of \dQuote{off}.  See "Custom Control" section for details.}

\item{options}{same as \code{search.path}}

\item{working.directory}{same as \code{search.path}}

\item{random.seed}{same as \code{search.path}}

\item{namespaces}{same as \code{search.path}}

\item{package}{character(1L) or NULL; if NULL will tell \code{unitize}
to attempt to identify if the test file is inside an R package folder
structure and if so run tests in that package's namespace.  This should
work with R CMD check tests as well as in normal usage.  If character will
take the value to be the name of the package to use the namespace of as
the parent environment.  Note that \code{in_pkg} does not retrieve the
environment, it just tells \code{unitize} to do so.}
}
\value{
for \code{state} a \code{unitizerStateRaw} object, for \code{in_pkg}
  a \code{unitizerInPkg} object, both of which are suitable as values for
  the \code{state} parameter for \code{\link{unitize}} or as values for the
  \dQuote{unitizer.state} global option.
}
\description{
While R generally adheres to a "functional" programming style, there are
several aspects of session state that can affect the results of code
evaluation (e.g. global environment, search path).  \code{unitizer} provides
functionality to increase test reproducibility by controlling session state
so that it is the same every time a test is run.  This functionality is
turned off by default to comply with CRAN requirements, and also because
there are inherent limitations in R that may prevent it from fully working in
some circumstances.  You can permanently enable the suggested state tracking
level by adding \code{options(unitizer.state='suggested')} in your
\code{.Rprofile}, although if you intend to do this be sure to read the
\dQuote{CRAN non-compliance} section.
}
\section{CRAN Non-Compliance and Other Caveats}{


In the default state management mode, this package fully complies with CRAN
policies.  In order to implement advanced state management features we must
lightly trace some \code{base} functions to alert \code{unitizer} each time
the search path is changed by a test expression.  The traced function
behavior is completely unchanged other than for the side effect of notifying
\code{unitizer} each time they are called.  Additionally, the functions are
only traced during \code{unitize} evaluation and are untraced on exit.
Unfortunately this tracing is against CRAN policies, which is why it is
disabled by default.

Arguably other aspects of state management employed outside of
\code{state="default"} _could_ be considered CRAN non-compliant, but none of
these are deployed unless you explicitly chose to do so.  Additionally,
\code{unitizer} limits state manipulation to the evaluation of its processes
and restores state on exit.  Some exceptional failures may prevent restoring
state fully.

If state management were to fail fail in an unhandled form, the simplest
work-around is to turn off state management altogether with
\code{state="default"}. If it is a particular aspect of state management
(e.g. search paths with packages attached with \code{devtools::load_all}),
you can disable just that aspect of state (see "Custom Control" section).

For more details see the reproducible tests vignette with:
\code{vignette(package='unitizer', 'u4_reproducible-tests')}
}

\section{Overview}{


You can control how \code{unitizer} manages state via
the state argument to \code{unitize} or by setting the
\dQuote{unitizer.state} option.  This help file discusses state
management with \code{unitizer}, and also documents two functions that, in
conjunction with \code{\link{unitize}} or \code{\link{unitize_dir}} allow you
to control state management.

\bold{Note}: most of what is written in this page about \code{unitize}
applies equally to \code{unitize_dir}.

\code{unitizer} provides functionality to insulate test code from variability
in the following.  Note the \dQuote{can be} wording because by default
these elements of state are not managed:

\itemize{
  \item Workspace / Parent Environment: all tests can be
     evaluated in environments that are children of a special environment
     that does not inherit from \code{.GlobalEnv}.  This prevents objects
     that are lying around in your workspace from interfering with your
     tests.
  \item Random Seed: can be set to a specific value at the
    beginning of each test file so that tests using random values get the
    same value at every test iteration. This only sets the seed at the
    beginning of each test file, so changes in order or number of functions
    that generate random numbers in your test file will affect subsequent
    tests.  The advantage of doing this over just setting the seed directly
    in the test files is that \code{unitizer} tracks the value of the seed
    and will tell you the seed changed for any given test (e.g. because you
    added a test in the middle of the file that uses the random seed).
  \item Working Directory: can be set to the tests directory
    inside the package directory if the test files appear to be inside the
    folder structure of a package, and the test file does not appear to be
    run as part of a check run (e.g. R CMD check,
    `tools::testInstalledPakage`).  If test files are not inside a package
    directory structure then can be set to the test files' directory.
  \item Search Path: can be set to what you would
    typically find in a freshly loaded vanilla R session.  This means any non
    default packages that are loaded when you run your tests are unloaded
    prior to running your tests.  If you want to use the same libraries
    across multiple tests you can load them with the \code{pre} argument to
    \code{\link{unitize}} or \code{\link{unitize_dir}}.  Due to limitations
    of R this is only an approximation to actually restarting R into a fresh
    session.
  \item Options: same as search path, but see "Namespaces" next.
  \item Namespaces: same as search path; this
    option is only made available to support options since many namespaces
    set options \code{onLoad}, and as such it is necessary to unload and
    re-load them to ensure default options are set.  See the "Namespaces and
    Options" section.
}

In the \dQuote{suggested} state tracking mode (previously known as
\dQuote{recommended}), parent environment, random seed, working directory,
and search path are all managed to level 2, which approximates what you would
find in a fresh session (see "Custom Control" section below).  For example,
with the search path managed, each test file will start evaluation with the
search path set to the tests folder of your package.  All these settings are
returned to their original values when \code{unitizer} exits.

To manage the search path \code{unitizer} detaches
and re-attaches packages.  This is not always the same as loading a package
into a fresh R session as detaching a package does not necessarily undo every
action that a package takes when it is loaded.  See \code{\link{detach}} for
potential pitfalls of enabling this setting.  Additionally, packages attached
in non-standard ways (e.g. \code{devtools::load_all}) may not re-attach
properly.

You can modify what aspects of state are managed by using the \code{state}
parameter to \code{\link{unitize}}.  If you are satisfied with basic default
settings you can just use the presets described in the next section.  If you
want more control you can use the return values of the \code{state} and
\code{in_pkg} functions as the values for the \code{state} parameter for
\code{unitize}.

State is reset after running each test file when running multiple test
files with \code{unitize_dir}, which means state changes in one test file
will not affect the next one.
}

\section{State Presets}{


For convenience \code{unitizer} provides several state management presets
that you can specify via the \code{state} parameter to \code{\link{unitize}}.
The simplest method is to specify the preset name as a character value:

\itemize{
  \item "suggested": \itemize{
      \item Use special (non \code{.GlobalEnv}) parent environemnt
      \item Manage search path
      \item Manage random seed (and set it to be of type "Wichmann-Hill"
        for space considerations).
      \item Manage workign directory
      \item Leave namespace and options untouched
    }
  \item "safe" like suggested, but turns off tracking for search path in
    addition to namespaces and options.  These settings, particularly the
    last two, are the most likely to cause compatibility problems.
  \item "pristine" implements the highest level of state tracking and control
  \item "basic" keeps all tracking, but at a less aggressive level; state is
    reset between each test file to the state before you started
    \code{unitize}ing so that no single test file affects another, but the
    state of your workspace, search path, etc. when you launch
    \code{unitizer} will affect all the tests (see the Custom Control)
    section.
  \item "off" (default) state tracking is turned off
}
}

\section{Custom Control}{


If you want to customize each aspect of state control you can pass a
\code{unitizerState} object as the \code{state} argument.  The simplest way
to do this is by using the \code{\link{state}} constructor function.  Look
at the examples for how to do this.

For convenience \code{unitize} allows you to directly specify a parent
environment if all you want to change is the parent evaluation environment
but are otherwise satisfied with the defaults.  You can even use the
\code{\link{in_pkg}} function to tell \code{unitizer} to use the namespace
associated with your current project, assuming it is an R package.  See
examples for details.

If you do chose to modify specific aspects of state control here is a guide
to what the various parameter values for \code{state} do:
\itemize{
  \item For \code{par.env}: any of the following:
    \itemize{
      \item \code{NULL} to use the special \code{unitizer} parent
        environment as the parent environment; this environment has for
        parent the parent of \code{.GlobalEnv}, so any tests evaluated
        therein will not be affected by objects in \code{.GlobalEnv}
        see (\code{vignette("unitizer_reproducible_state")}).
      \item an environment to use as the parent evaluation environment
      \item the name of a package to use that package's namespace
        environment as the parent environment
      \item the return value of \code{in_pkg}; used primarily to autodetect
        what package namespace to use based on package directory structure
    }
  \item For all other slots, the settings are in \code{0:2} and mean:
    \itemize{
      \item 0 turn off state tracking
      \item 1 track, but start with state as it was when \code{unitize} was
        called.
      \item 2 track and set state to what you would typically find in a clean
        R session, with the exception of \code{random.seed}, which is
        set to \code{getOption("unitizer.seed")} (of kind "Wichmann-Hill"
        as that seed is substantially smaller than the R default seed).
} }

If you chose to use level \code{1} for the random seed you should consider
picking a random seed type before you start unitizer that is small like
"Wichman-Hill" as the seed will be recorded each time it changes.
}

\section{Permanently Setting State Tracking}{


You can permanently change the default state by setting the
\dQuote{unitizer.state} option to the name of the state presets above or to a
or to a state settings option object generated with \code{state} as described
in the previous section.
}

\section{Avoiding \code{.GlobalEnv}}{


For the most part avoiding \code{.GlobalEnv} leads to more robust and
reproducible tests since the tests are not influenced by objects in the
workspace that may well be changing from test to test.  There are some
potential issues when dealing with functions that expect \code{.GlobalEnv} to
be on the search path.  For example, \code{setClass} uses \code{topenv} to
find a default environment to assign S4 classes to.  Typically this will be
the package environment, or \code{.GlobalEnv}.  However, when you are in
\code{unitizer} this becomes the next environment on the search path, which
is typically locked, which will cause \code{setClass} to fail.  For those
types of functions you should specify them with an environment directly, e.g.
\code{setClass("test", slots=c(a="integer"), where=environment())}.
}

\section{Namespaces and Options}{


Options and namespace state management require the ability to fully unload
any non-default packages and namespaces, and there are some packages that
cannot be unloaded, or should not be unloaded (e.g.
\href{https://github.com/Rdatatable/data.table/issues/990}{data.table}).  I
some systems it may even be impossible to fully unload any compiled code
packages (see \code{\link{detach}}. If you know the packages you typically
load in your sessions can be unloaded, you can turn this functionality on by
setting \code{options(unitizer.state="pristine")} either in your session, in
your \code{.Rprofile} file, or using \code{state="prisitine"} in each call to
\code{unitize} or \code{unitize_dir}.  If you have packages that cannot be
unloaded, but you still want to enable these features, see the "Search Path
and Namespace State Options" section of \code{\link{unitizer.opts}} docs.

If you run \code{unitizer} with options and namespace tracking and you run
into a namespace that cannot be unloaded, or should not be unloaded because
it is listed in \code{getOption("unitizer.namespace.keep")}, \code{unitizer}
will turn off \code{options} state tracking from that point onwards.

Additionally, note that \code{warn} and \code{error} options are always set
to \code{1} and \code{NULL} respectively during test evaluation, irrespective
of what option state tracking level you select.
}

\section{Known Untracked State Elements}{


\itemize{
  \item system time: tests involving functions such as \code{\link{date}}
    will inevitably fail
  \item locale: is not tracked because it so specific to the system and so
    unlikely be be changed by user action; if you have tests that depend on
    locale be sure to set the locale via the \code{pre} argument to
    \code{\link{unitize}}, and also to reset it to the original value in
    \code{post}.
}
}

\examples{
\dontrun{
## In this examples we use `...` to denote other arguments to `unitize` that
## you should specify.  All examples here apply equally to `unitize_dir`

## Run with suggested state tracking settings
unitize(..., state="suggested")
## Manage as much of state as possible
unitize(..., state="pristine")

## No state management, but evaluate with custom env as parent env
my.env <- new.env()
unitize(..., state=my.env)
## use custom environment, and turn on search.path tracking
## here we must use the `state` function to construct a state object
unitize(..., state=state(par.env=my.env, search.path=2))

## Specify a namespace to run in by name
unitize(..., state="stats")
unitize(..., state=state(par.env="stats")) # equivalent to previous

## Let `unitizer` figure out the namespace from the test file location;
## assumes test file is inside package folder structure
unitize("mytests.R", state=in_pkg()) # assuming mytests.R is part of a pkg
unitize("mytests.R", state=in_pkg("mypkg")) # also works
}
}
\seealso{
\code{\link{unitize}}, \code{\link{unitizer.opts}}
}
