% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/verify.R
\name{unit_test}
\alias{unit_test}
\title{Add or modify unit tests}
\usage{
unit_test(object, test, expr, label, conditions = list(), active = TRUE)
}
\arguments{
\item{object}{Stock-and-flow model, object of class \code{\link{stockflow}}.}

\item{test}{Integer number of the test to modify. Must be a positive integer
(a warning is issued and the value rounded when a non-integer is
supplied). When \code{test} exceeds the current number of tests a warning is
issued and a new test is appended instead. Can be omitted when adding a
new test.}

\item{expr}{An expression to evaluate against simulation results. Variable
names in the expression refer to model variables; each resolves to a
numeric vector of time-series values. Required when adding a new test;
optional when modifying (keeps the current expression if omitted).}

\item{label}{A descriptive label for the test. If omitted when adding,
auto-generated from \code{expr}. If omitted when modifying, the current label
is kept. Labels must be unique.}

\item{conditions}{A named list of constant or initial stock overrides used
when evaluating this test. If non-empty, \code{\link[=verify.stockflow]{verify.stockflow()}} will
re-simulate the model with these parameter values before evaluating \code{expr}.}

\item{active}{If \code{FALSE}, the test is defined but skipped during
\code{\link[=verify]{verify()}}. Defaults to \code{TRUE}.}
}
\value{
The model object with the unit test added or modified, invisibly.
}
\description{
Unit tests are assertions about model behavior that can be evaluated against
simulation results. For example, you might assert that a stock remains
non-negative, or that a certain variable reaches a threshold by the end of
the simulation. Unit tests can be added to a model such that they can be
evaluated with \code{\link[=verify]{verify()}}. All unit tests can be displayed with
\code{unit_tests()}.
}
\details{
The \code{expr} argument accepts a plain logical expression:
\itemize{
\item \strong{Logical}: \code{all(S >= 0)}, \code{cor(D, C) < -.5}.
}

When \code{label} is omitted, a human-readable label is generated automatically
by parsing the expression (e.g., \code{all(S >= 0)} →
\code{"S is at least 0 (for all values)"}).
}
\section{Adding vs. modifying}{

\itemize{
\item \strong{Add} a new test: omit \code{test} (and provide a \code{label} that does not match
any existing test, or omit \code{label} to auto-generate one).
\item \strong{Modify} an existing test by number: supply \code{test} (integer).
\item \strong{Modify} an existing test by label: supply a \code{label} that matches an
existing test (without specifying \code{test}).
}

When modifying, only the arguments you explicitly supply are changed; all
other fields keep their current value.
}

\section{Uniqueness}{

Labels must be unique across all unit tests. An error is thrown if a new
or modified label would create a duplicate. Expressions must also be unique;
an error is thrown if an identical \code{expr} already exists on another test.
}

\examples{
sfm <- stockflow("sir") |>
  unit_test(expr = all(susceptible >= 0))

# Run unit tests
verify(sfm)

# Add test with label
sfm <- unit_test(sfm,
  label = "recovered increases",
  expr = all(diff(recovered) >= 0)
)
verify(sfm)

# Add test with conditions
sfm <- unit_test(sfm,
  expr = all(infected == infected[1]),
  label = "When infection_rate is zero, no one gets infected",
  conditions = list(infection_rate = 0)
)
verify(sfm)

# View all tests
unit_tests(sfm)

# Deactivate test test 1
sfm <- unit_test(sfm, test = 1, active = FALSE)
verify(sfm)

# Modify test by label, e.g., to change the expression
sfm <- unit_test(sfm,
  label = "recovered increases over time",
  expr = all(diff(recovered) > -1)
)
verify(sfm)

}
\seealso{
\code{\link[=verify]{verify()}}, \code{\link[=unit_tests]{unit_tests()}}, \code{\link[=discard_unit_test]{discard_unit_test()}}
}
\concept{unitTest}
