Title: | 'SciViews' - Unit, Integration and System Testing |
---|---|
Description: | A complete unit test system. |
Authors: | Philippe Grosjean [aut, cre] |
Maintainer: | Philippe Grosjean <[email protected]> |
License: | GPL-2 |
Version: | 1.0.6 |
Built: | 2024-10-27 05:35:22 UTC |
Source: | https://github.com/SciViews/svUnit |
These functions define the assertions in test functions. They are designed to check the result of some test calculation.
checkEquals( target, current, msg = "", tolerance = .Machine$double.eps^0.5, checkNames = TRUE, ... ) checkEqualsNumeric( target, current, msg = "", tolerance = .Machine$double.eps^0.5, ... ) checkIdentical(target, current, msg = "") checkTrue(expr, msg = "") checkException(expr, msg = "", silent = getOption("svUnit.silentException")) DEACTIVATED(msg = "")
checkEquals( target, current, msg = "", tolerance = .Machine$double.eps^0.5, checkNames = TRUE, ... ) checkEqualsNumeric( target, current, msg = "", tolerance = .Machine$double.eps^0.5, ... ) checkIdentical(target, current, msg = "") checkTrue(expr, msg = "") checkException(expr, msg = "", silent = getOption("svUnit.silentException")) DEACTIVATED(msg = "")
target |
a target object as reference for comparison. |
current |
An object created for comparison (not an S4 class object). |
msg |
An optional (short!) message to document a test. This message is stored in the log and printed in front of each test report. |
tolerance |
numeric >= 0. A numeric check does not fail if differences are smaller than 'tolerance'. |
checkNames |
Flag, if |
... |
Optional arguments passed to |
expr |
Syntactically valid R expression which can be evaluated and must
return a logical vector ( |
silent |
Flag passed on to try, which determines if the error message
generated by the checked function is displayed at the R console. By default,
it is |
These check functions are equivalent to various methods of the class
junit.framework.Assert of Java junit framework. They should be
code-compatible with functions of same name in 'RUnit' 0.4.17, except
for checkTrue()
that is vectorized here, but accept only a scalar result in
'RUnit'. For scalar test, the behavior of the function is the same in both
packages.
See svTest()
for examples of use of these functions in
actual test cases attached to R objects.
See also the note about S4 objects in the RUnit::checkTrue()
online help of the
'RUnit' package.
These function return TRUE
if the test succeeds, FALSE
if it fails,
possibly with a 'result' attribute containing more information about the
problem. This is very different from corresponding functions in 'RUnit' that
stop with an error in case of test failure. Consequently, current functions
do not require the complex evaluation framework designed in 'RUnit' for that
reason.
Written by Ph. Grosjean, inspired from the general design of the 'RUnit' package by Thomas Konig, Klaus Junemann & Matthias Burger.
svTest()
, Log()
, guiTestReport()
, RUnit::checkTrue
clearLog() # Clear the svUnit log # All these tests are correct (checkEquals(c("A", "B", "C"), LETTERS[1:3])) (checkEqualsNumeric(1:10, seq(1, 10))) (checkIdentical(iris[1:50, ], iris[iris$Species == "setosa",])) (checkTrue(1 < 2)) (checkException(log("a"))) Log() # See what's recorded in the log # ... but these ones fail (checkEquals("A", LETTERS[1:3])) (checkEqualsNumeric(2:11, seq(1, 10))) (checkIdentical(iris[1:49, ], iris[iris$Species == "setosa",])) (checkTrue(1 > 2)) (checkException(log(1))) Log() # See what's recorded in the log # Create a test function and run it foo <- function(x, y = 2) return(x * y) test(foo) <- function() { #DEACTIVATED() checkEqualsNumeric(5, foo(2)) checkEqualsNumeric(6, foo(2, 3)) checkTrue(is.test(foo)) checkTrue(is.test(test(foo))) checkIdentical(test(foo), attr(foo, "test")) checkException(foo("b")) checkException(foo(2, "a")) } (runTest(foo)) # Of course, everything is recorded in the log Log() clearLog()
clearLog() # Clear the svUnit log # All these tests are correct (checkEquals(c("A", "B", "C"), LETTERS[1:3])) (checkEqualsNumeric(1:10, seq(1, 10))) (checkIdentical(iris[1:50, ], iris[iris$Species == "setosa",])) (checkTrue(1 < 2)) (checkException(log("a"))) Log() # See what's recorded in the log # ... but these ones fail (checkEquals("A", LETTERS[1:3])) (checkEqualsNumeric(2:11, seq(1, 10))) (checkIdentical(iris[1:49, ], iris[iris$Species == "setosa",])) (checkTrue(1 > 2)) (checkException(log(1))) Log() # See what's recorded in the log # Create a test function and run it foo <- function(x, y = 2) return(x * y) test(foo) <- function() { #DEACTIVATED() checkEqualsNumeric(5, foo(2)) checkEqualsNumeric(6, foo(2, 3)) checkTrue(is.test(foo)) checkTrue(is.test(test(foo))) checkIdentical(test(foo), attr(foo, "test")) checkException(foo("b")) checkException(foo(2, "a")) } (runTest(foo)) # Of course, everything is recorded in the log Log() clearLog()
These functions are usually not called from the command line. They return data to compatible GUI clients, like Komodo Edit with the SciViews-K extension.
guiTestReport(object, sep = "\t", path = NULL, ...) guiSuiteList(sep = "\t", path = NULL, compare = TRUE) guiSuiteAutoList(...) guiTestFeedback(object, path = NULL, ...)
guiTestReport(object, sep = "\t", path = NULL, ...) guiSuiteList(sep = "\t", path = NULL, compare = TRUE) guiSuiteAutoList(...) guiTestFeedback(object, path = NULL, ...)
object |
a 'svUnitData' object. |
sep |
Field separator to use in the results. |
path |
Path where to write a 'Suites.txt' file with the list of
currently available test suites (to be used by the GUI client). If |
... |
Not used currently. |
compare |
Do we compare the list of available test suite and return
something to the GUI client only if there are changes in the list? This is
used (when |
guiSuiteList()
returns the list of available test suites invisibly.
guiSuiteAutoList()
is used to establish a callback to automatically list
the available test suites in the GUI. It is not intended to be called
directly by the user. The other functions just return TRUE
invisibly.They
are used for their side effect of sending data to compatible GUI clients.
Philippe Grosjean
svTest()
, svSuite()
, koUnit_version()
These functions allow controlling the test unit module (R Unit tab at right)
in Komodo with SciViews-K and SciViews-K Unit extensions. R must be correctly
connected to Komodo, meaning that the 'svGUI' package must be loaded with
proper configuration of client/server socket connections between R and
Komodo. See the manual about SciViews-K for more information. The functions
defined here are the same as JavaScript functions defined in the 'sv.r.unit'
namespace in Komodo/SciViews-K Unit. For instance, koUnit_runTest()
is
equivalent to sv.r.unit.runTest();
in a Javascript macro in Komodo.
koUnit_setAutoTest(state) koUnit_isAutoTest() koUnit_runTest() koUnit_showRUnitPane(state) koUnit_version()
koUnit_setAutoTest(state) koUnit_isAutoTest() koUnit_runTest() koUnit_showRUnitPane(state) koUnit_version()
state |
|
koUnit_isAutoTest()
returns TRUE
if the test unit is in auto mode in
Komodo (the selected tests are run automatically each time a .R file
edited in Komodo is saved).
koUnit_version()
returns the version for which the SciViews-K Unit
extension was designed for. This allow to check if this version is compatible
with current 'svUnit' R package version, and to propose to update the Komodo
extension if needed (this mechanism is not running currently, but it will be
implemented in the future to avoid or limit incompatibilities between
respective R and Komodo extensions).
The other functions are invoked for their side-effect and they return nothing. Note, however, that correct execution of this code in Komodo is verified, and the functions issue an error in R if they fail to execute correctly in Komodo.
Philippe Grosjean
## Not run: # Make sure R is communicating with Komodo before use, see ?koCmd in svGUI koUnit_version() # Toggle visibility of the R Unit pane in Komodo twice koUnit_showRUnitPane() koUnit_showRUnitPane() # Make sure that the R Unit pane is visible koUnit_showRUnitPane(TRUE) # Is the test unit running in auto mode? koUnit_isAutoTest() # Toggle auto test mode off koUnit_setAutoTest(FALSE) # Run the test units from within Komodo koUnit_runTest() ## End(Not run)
## Not run: # Make sure R is communicating with Komodo before use, see ?koCmd in svGUI koUnit_version() # Toggle visibility of the R Unit pane in Komodo twice koUnit_showRUnitPane() koUnit_showRUnitPane() # Make sure that the R Unit pane is visible koUnit_showRUnitPane(TRUE) # Is the test unit running in auto mode? koUnit_isAutoTest() # Toggle auto test mode off koUnit_setAutoTest(FALSE) # Run the test units from within Komodo koUnit_runTest() ## End(Not run)
These functions define the code of test functions. They are designed to check the result of some test calculation.
Log(description = NULL) createLog(description = NULL, deleteExisting = FALSE) clearLog() errorLog(stopit = TRUE, summarize = TRUE) lastTest() lastSuite()
Log(description = NULL) createLog(description = NULL, deleteExisting = FALSE) clearLog() errorLog(stopit = TRUE, summarize = TRUE) lastTest() lastSuite()
description |
A (short) character string describing this test suite log. |
deleteExisting |
Do we delete an existing a |
stopit |
Do we issue an error ( |
summarize |
Should the summary of the log be printed in case we stop
execution of the code when an error is found (see |
svUnit records results of assertions (using the checkxxx() functions) in a
'svSuiteData' object named .Log
and located in .GlobalEnv. Hence, this log
is easy to access. However, in order to avoid errors in your code in case
this object was deleted, or not created, it is better to access it using
Log()
which take care to create the object if it is missing.
Log()
and createLog()
return the .Log
object defined in .GlobalEnv
by
reference (it is indeed an environment). So, you can use its content (and
change it, if you write functions to manipulate this log).
clearLog()
return invisibly TRUE
or FALSE
, depending if an existing log
object was deleted or not.
errorLog()
is mainly used for its side-effect of stopping code execution
and/or printing a summary of the test runs in the context of example
massaging in R CMD check (see the "Writing R extensions" manual). However,
this function also returns invisibly a contingency table with the number of
successes, failures, errors and deactivated tests recorded so far.
lastTest()
and lastSuite()
recall results of last test and last suite
run, respectively.
Philippe Grosjean
svSuiteData()
, svSuite()
, svTest()
, checkEquals()
clearLog() # Clear the svUnit log # Two correct tests (checkTrue(1 < 2)) (checkException(log("a"))) errorLog() # Nothing, because there is no error ## Not run: (checkTrue(1 > 2)) # This test fails lastTest() # Print results of last test errorLog() # Stop and summarize the tests run so far ## End(Not run) clearLog()
clearLog() # Clear the svUnit log # Two correct tests (checkTrue(1 < 2)) (checkException(log("a"))) errorLog() # Nothing, because there is no error ## Not run: (checkTrue(1 > 2)) # This test fails lastTest() # Print results of last test errorLog() # Stop and summarize the tests run so far ## End(Not run) clearLog()
Test functions are functions without arguments with class 'svTest' containing
one or more assertions using checkxxx()
functions. They can be
attached to any object as a 'test' attribute. They can also be transferred
into a more formal test unit file on disk by applying the makeUnit()
method.
makeTestListFromExamples(packageName, manFilesDir, skipFailing = FALSE) svTest(testFun) ## S3 method for class 'svTest' print(x, ...) as.svTest(x) is.svTest(x) is.test(x) test(x) test(x) <- value makeUnit(x, ...) ## Default S3 method: makeUnit( x, name = make.names(deparse(substitute(x))), dir = tempdir(), objfile = "", codeSetUp = NULL, codeTearDown = NULL, ... ) ## S3 method for class 'svTest' makeUnit( x, name = make.names(deparse(substitute(x))), dir = tempdir(), objfile = "", codeSetUp = NULL, codeTearDown = NULL, ... ) runTest(x, ...) ## Default S3 method: runTest( x, name = deparse(substitute(x)), objfile = "", tag = "", msg = "", ... ) ## S3 method for class 'list' runTest(x, ...) ## S3 method for class 'svTest' runTest( x, name = deparse(substitute(x)), objfile = "", tag = "", msg = "", ... )
makeTestListFromExamples(packageName, manFilesDir, skipFailing = FALSE) svTest(testFun) ## S3 method for class 'svTest' print(x, ...) as.svTest(x) is.svTest(x) is.test(x) test(x) test(x) <- value makeUnit(x, ...) ## Default S3 method: makeUnit( x, name = make.names(deparse(substitute(x))), dir = tempdir(), objfile = "", codeSetUp = NULL, codeTearDown = NULL, ... ) ## S3 method for class 'svTest' makeUnit( x, name = make.names(deparse(substitute(x))), dir = tempdir(), objfile = "", codeSetUp = NULL, codeTearDown = NULL, ... ) runTest(x, ...) ## Default S3 method: runTest( x, name = deparse(substitute(x)), objfile = "", tag = "", msg = "", ... ) ## S3 method for class 'list' runTest(x, ...) ## S3 method for class 'svTest' runTest( x, name = deparse(substitute(x)), objfile = "", tag = "", msg = "", ... )
packageName |
A character string identifying the package from which to extract examples. |
manFilesDir |
A character string identifying the directory holding the manual pages and examples. |
skipFailing |
A logical indicating whether missing or failing
documentation examples should be marked as |
testFun |
A function without arguments defining assertions (using
|
x |
Any kind of object. |
... |
Further arguments to the method (not used yet). |
value |
The tests to place in the object (as 'test' attribute); could be
a 'svTest' object, or a function without arguments with
assertions ( |
name |
The name of a test. |
dir |
The directory where to create the test unit file. |
objfile |
The path to the file containing the original source code of the object being tested. This argument is used to bring a context for a test and allow a GUI to automatically open the source file for edition when the user clicks on a test that failed or raised an error. |
codeSetUp |
An expression with some code you want to add to the
|
codeTearDown |
An expression with some code you want to add to the
|
tag |
A tag is a character string identifying a location in source code
files (either a test unit file, or the original source code of the tested
objects defined in |
msg |
A message you want to associate with this test run. |
A 'svTest' object for svTest()
, as.svTest()
and test()
. Function
is.svTest()
returns TRUE
if 'x' is a 'svTest' object, and is.test()
does the same but also looks in the 'test' attribute if the class of 'x' is
not 'svTest' and returns TRUE
if it finds something there.
makeUnit()
takes an object, extract its test function and write it in a
sourceable test unit on the disk (it should be compatible with 'RUnit' test
unit files too).
runTest()
returns invisibly a 'svTestData' object with all results after running specified tests.
Philippe Grosjean
svSuite()
, is.svTestData()
, Log()
, checkEquals()
clearLog() # Clear the log file foo <- function(x, y = 2) return(x * y) is.test(foo) # No # Create test cases for this function test(foo) <- function() { checkEqualsNumeric(4, foo(2)) checkEqualsNumeric(6, foo(2, 3)) checkTrue(is.test(foo)) checkTrue(is.test(test(foo))) checkIdentical(attr(foo, "test"), test(foo)) checkException(foo(2, "aa")) checkException(foo("bb")) } is.test(foo) # Yes ## Not run: # Create a test unit on disk and view it unit <- makeUnit(foo) file.show(unit, delete.file = TRUE) ## End(Not run) # Run the test (runTest(foo)) # Same as... bar <- test(foo) (runTest(bar)) # How fast can we run 100 times such kind of tests (700 test in total)? # (just an indication because in real situation with test unit files, we # have also the time required to source the units!) system.time(for (i in 1:100) runTest(foo))[3] is.svTest(test(foo)) # Yes, of course! # When an object without associated test is passed to runTest(), # a simple test containing only a DEACTIVATED entry is build x <- 1:10 summary(runTest(x)) summary(Log()) rm(foo, bar, x)
clearLog() # Clear the log file foo <- function(x, y = 2) return(x * y) is.test(foo) # No # Create test cases for this function test(foo) <- function() { checkEqualsNumeric(4, foo(2)) checkEqualsNumeric(6, foo(2, 3)) checkTrue(is.test(foo)) checkTrue(is.test(test(foo))) checkIdentical(attr(foo, "test"), test(foo)) checkException(foo(2, "aa")) checkException(foo("bb")) } is.test(foo) # Yes ## Not run: # Create a test unit on disk and view it unit <- makeUnit(foo) file.show(unit, delete.file = TRUE) ## End(Not run) # Run the test (runTest(foo)) # Same as... bar <- test(foo) (runTest(bar)) # How fast can we run 100 times such kind of tests (700 test in total)? # (just an indication because in real situation with test unit files, we # have also the time required to source the units!) system.time(for (i in 1:100) runTest(foo))[3] is.svTest(test(foo)) # Yes, of course! # When an object without associated test is passed to runTest(), # a simple test containing only a DEACTIVATED entry is build x <- 1:10 summary(runTest(x)) summary(Log()) rm(foo, bar, x)
A 'svSuite' object is essentially a list of test units directories (or packages, in this case, corresponding directories are PKG/unitTests and its subdirectories), and of object names containing tests to add temporarily to the test suite. These must be formatted in a concise way as described for the 'tests' argument.
svSuite(tests) as.svSuite(x) is.svSuite(x) ## S3 method for class 'svSuite' print(x, ...) svSuiteList( packages = TRUE, objects = TRUE, dirs = getOption("svUnit.dirs"), excludeList = getOption("svUnit.excludeList"), pos = .GlobalEnv, loadPackages = FALSE ) ## S3 method for class 'svSuite' makeUnit( x, name = make.names(deparse(substitute(x))), dir = tempdir(), objfile = "", codeSetUp = NULL, codeTearDown = NULL, pos = .GlobalEnv, ... ) ## S3 method for class 'svSuite' runTest(x, name = make.names(deparse(substitute(x))), unitname = NULL, ...)
svSuite(tests) as.svSuite(x) is.svSuite(x) ## S3 method for class 'svSuite' print(x, ...) svSuiteList( packages = TRUE, objects = TRUE, dirs = getOption("svUnit.dirs"), excludeList = getOption("svUnit.excludeList"), pos = .GlobalEnv, loadPackages = FALSE ) ## S3 method for class 'svSuite' makeUnit( x, name = make.names(deparse(substitute(x))), dir = tempdir(), objfile = "", codeSetUp = NULL, codeTearDown = NULL, pos = .GlobalEnv, ... ) ## S3 method for class 'svSuite' runTest(x, name = make.names(deparse(substitute(x))), unitname = NULL, ...)
tests |
A character string with items to include in the test suite. It could be 'package:PKG' for including test units located in the /unitTests subdirectory of the package PGK, or 'package:PKG (SUITE)' for test units located in the subdirectory /unitTests/SUITE of package PKG, or 'dir:MYDIR' for including test units in MYDIR, or 'test(OBJ)' for tests embedded in an object, or 'OBJ' for 'svTest' object directly. |
x |
Any kind of object. |
... |
Further arguments to pass to |
packages |
Do we list test units available in loaded packages? Alternatively one can provide a character vector of package names, and it will be used to filter packages (take care: in this case it will look at installed packages, not only loaded packages)! |
objects |
Do we list test available in objects? Alternatively, one can provide a character vector of object names, and it will filter objects in 'pos' according to this vector. |
dirs |
An additional list of directories where to look for more test units. For convenience, this list can simply be saved as an 'svUnit.dirs' options. |
excludeList |
A list of items to exclude from the listing. The function
uses regular expression to match the exclusions. So, for instance, specifying
|
pos |
The environment to look for 'objects' (environment, character string with name of an environment, or integer with position of the environment in the search path. |
loadPackages |
In the case a list of packages is provided in
|
name |
The name of the test suite to build. |
dir |
The directory where to create the test unit file. |
objfile |
The path to the file containing the original source code of the object being tested. This argument is used to bring a context for a test and allow a GUI to automatically open the source file for edition when the user clicks on a test that failed or raised an error. |
codeSetUp |
An expression with some code you want to add to the
|
codeTearDown |
An expression with some code you want to add to the
|
unitname |
The name of a unit to run inside the suite. If |
svSuiteList()
lists all loaded packages having /unitTests/runit*.R files
(or similar files in subdirectories), and all objects in the user workspace
that have a 'test' attribute, or are 'svTest' objects (by default). It is a
rather exhaustive list of all test items currently available in the current R
session, but restricted by getOption("svUnit.excludeList")
.
makeUnit()
writes a test unit on disk with the tests from the objects
listed in the 'svSuite' object that do not belong yet to a test unit.
runTest()
runs all the test in packages, directories and objects listed in
the 'svSuite' object.
Thanks to the variety of sources allowed for tests, it is possible to define these tests in a structured way, inside packages, like for the 'RUnit' package (but with automatic recognition of test units associated to packages, in the present case). It is also easy to define tests more loosely by just attaching those tests to the objects you want to check. Whenever there objects are loaded in the user's workspace, their tests are available. In both cases, a test unit file on disk is sourced in a local environment and test functions are run (same approach as in the 'RUnit' package, and the same test unit files should be compatibles with both 'RUnit' and 'svUnit' packages), but in the case of a loosely definition of the tests by attachment to objects, the test unit file is created on the fly in the temporary directory (by default).
At any time, you can transform a series of tests loosely attached to objects
into a test unit file by applying makeUnit()
to a 'svSuite' object,
probably specifying another directory than the (default) temporary dir for
more permanent storage of your test unit file. The best choice is the
'/inst/unitTests' directory of a package source, or one of its
subdirectories. That way, your test unit file(s) will be automatically listed
and available each time you load the compiled package in R (if you list them
using svSuiteList()
). Of course, you still can exclude tests from given
packages by adding 'package:PKG' in the exclusion list with something
like: options(svUnit.excludeList = c(getOption("svUnit.excludeList"), "package:PKG"))
.
svSuite()
, as.svSuite()
and svSuiteList()
return a 'svSuite' object.
is.svSuite()
returns TRUE
if the object is an 'svSuite'.
makeUnit()
creates a test unit file on disk, and runTest()
runs the tests
in such a file. They are used for their side-effect, but the first one also
returns the file created, and the second one returns invisibly the list of
all test unit files that where sourced ans run.
Philippe Grosjean
svSuiteData()
, svTest()
, Log()
, checkEquals()
, RUnit::checkEquals()
svSuiteList() # List all currently available test units and test cases # Exclusion list is used (regular expression filtering!). It contains: (oex <- getOption("svUnit.excludeList")) # Clear it, and relist available test units options(svUnit.excludeList = NULL) svSuiteList() # Two functions that include their test cases Square <- function(x) return(x^2) test(Square) <- function() { checkEquals(9, Square(3)) checkEquals(c(1, 4, 9), Square(1:3)) checkException(Square("xx")) } Cube <- function(x) return(x^3) test(Cube) <- function() { checkEquals(27, Cube(3)) checkEquals(c(1, 8, 28), Cube(1:3)) checkException(Cube("xx")) } # A separate test case object (not attached to a particular object) # This is the simplest way to define quick and durty integration tests test_Integrate <- svTest(function() { checkTrue(1 < 2, "check1") v <- 1:3 # The reference w <- 1:3 # The value to compare to the reference checkEquals(v, w) }) # A function without test cases (will be filtered out of the suite list) foo <- function(x) return(x) # Look now which tests are available svSuiteList() # Only objects, no package units svSuiteList(packages = FALSE) ## Not run: # Create the test unit file for all objects with tests in .GlobalEnv myunit <- makeUnit(svSuiteList(), name = "AllTests") file.show(myunit, delete.file = TRUE) ## End(Not run) # Filter objects using a list (object with/without tests and a nonexisting obj) svSuiteList(packages = FALSE, objects = c("Cube", "foo", "bar")) # Create another svSuite object with selected test items (mysuite <- svSuite(c("package:svUnit (VirtualClass)", "test(Cube)"))) is.svSuite(mysuite) # Should be! ## Not run: # Run all the tests currently available (runTest(svSuiteList(), name = "AllTests")) summary(Log()) ## End(Not run) # Restore previous exclusion list, and clean up the environment options(svUnit.excludeList = oex) rm(Square, Cube, foo, test_Integrate, mysuite, myunit, oex)
svSuiteList() # List all currently available test units and test cases # Exclusion list is used (regular expression filtering!). It contains: (oex <- getOption("svUnit.excludeList")) # Clear it, and relist available test units options(svUnit.excludeList = NULL) svSuiteList() # Two functions that include their test cases Square <- function(x) return(x^2) test(Square) <- function() { checkEquals(9, Square(3)) checkEquals(c(1, 4, 9), Square(1:3)) checkException(Square("xx")) } Cube <- function(x) return(x^3) test(Cube) <- function() { checkEquals(27, Cube(3)) checkEquals(c(1, 8, 28), Cube(1:3)) checkException(Cube("xx")) } # A separate test case object (not attached to a particular object) # This is the simplest way to define quick and durty integration tests test_Integrate <- svTest(function() { checkTrue(1 < 2, "check1") v <- 1:3 # The reference w <- 1:3 # The value to compare to the reference checkEquals(v, w) }) # A function without test cases (will be filtered out of the suite list) foo <- function(x) return(x) # Look now which tests are available svSuiteList() # Only objects, no package units svSuiteList(packages = FALSE) ## Not run: # Create the test unit file for all objects with tests in .GlobalEnv myunit <- makeUnit(svSuiteList(), name = "AllTests") file.show(myunit, delete.file = TRUE) ## End(Not run) # Filter objects using a list (object with/without tests and a nonexisting obj) svSuiteList(packages = FALSE, objects = c("Cube", "foo", "bar")) # Create another svSuite object with selected test items (mysuite <- svSuite(c("package:svUnit (VirtualClass)", "test(Cube)"))) is.svSuite(mysuite) # Should be! ## Not run: # Run all the tests currently available (runTest(svSuiteList(), name = "AllTests")) summary(Log()) ## End(Not run) # Restore previous exclusion list, and clean up the environment options(svUnit.excludeList = oex) rm(Square, Cube, foo, test_Integrate, mysuite, myunit, oex)
The 'svSuiteData' object contains results of all test run in one or more test
suites. The checkxxx()
functions and the runTest()
method generate data
(objects 'svTestData') contained in the default 'svSuiteData' named .Log
and located in .GlobalEnv
. It is then possible to display and report
information it contains in various ways to analyze the results.
is.svSuiteData(x) ## S3 method for class 'svSuiteData' stats(object, ...) metadata(object, ...) ## S3 method for class 'svSuiteData' metadata( object, fields = c("R.version", "sessionInfo", "time", "description"), ... ) ## S3 method for class 'svSuiteData' print(x, all = FALSE, file = "", append = FALSE, ...) ## S3 method for class 'svSuiteData' summary(object, ...) protocol(object, type = "text", file = "", append = FALSE, ...) ## Default S3 method: protocol(object, type = "text", file = "", append = FALSE, ...) ## S3 method for class 'svSuiteData' protocol(object, type = "text", file = "", append = FALSE, ...) protocol_text(object, file = "", append = FALSE, ...) ## S3 method for class 'svSuiteData' protocol_text(object, file = "", append = FALSE, ...) protocol_junit(object, ...) ## S3 method for class 'svSuiteData' protocol_junit(object, file = "", append = FALSE, ...)
is.svSuiteData(x) ## S3 method for class 'svSuiteData' stats(object, ...) metadata(object, ...) ## S3 method for class 'svSuiteData' metadata( object, fields = c("R.version", "sessionInfo", "time", "description"), ... ) ## S3 method for class 'svSuiteData' print(x, all = FALSE, file = "", append = FALSE, ...) ## S3 method for class 'svSuiteData' summary(object, ...) protocol(object, type = "text", file = "", append = FALSE, ...) ## Default S3 method: protocol(object, type = "text", file = "", append = FALSE, ...) ## S3 method for class 'svSuiteData' protocol(object, type = "text", file = "", append = FALSE, ...) protocol_text(object, file = "", append = FALSE, ...) ## S3 method for class 'svSuiteData' protocol_text(object, file = "", append = FALSE, ...) protocol_junit(object, ...) ## S3 method for class 'svSuiteData' protocol_junit(object, file = "", append = FALSE, ...)
x |
Any kind of object, or a 'svSuiteData' object in the case of
|
object |
A 'svSuiteData' object. |
... |
Further arguments to pass to methods. Not used yet. |
fields |
Character vector. The name of all metadata items you want to extract for the object. The default value is an exhaustive list of all available metadata (i.e., defined by default) in the object, but you can add more: just add a corresponding attribute to your object. |
all |
Do we print concise report for all test, or only for the tests that fail or produce an error? |
file |
Character. The path to the file where to write the report.
If |
append |
Do we append to this file? |
type |
Character. The type of protocol report to create. For the moment,
only |
A 'svSuiteData' is, indeed, an environment. The results for the various tests runs are in non hidden (i.e., names not starting with a dot) objects that are of class 'svTestData' in this environment. Various other objects that control the execution of the test, their context, etc. are contained as hidden objects with name starting with a dot. Note that using an environment instead of a list for this object allows for a call by reference instead of a usual call by value in R, when passing this object to a function. This property is largely exploited in all svUnit functions to make sure results of test runs are centralized in the same log ('svSuiteData' object).
is.svSuiteData()
returns TRUE
if the object is an 'svSuiteData'. The
various methods serve to extract or print content in the object.
Philippe Grosjean; Mario Frasca for the junit protocol.
svSuite()
, is.svTestData()
, Log()
, checkEquals()
clearLog() # Clear any existing log # Run some tests checkTrue(1 < 2) checkException(log("a")) foo <- function(x, y = 2) return(x * y) test(foo) <- function() { checkEqualsNumeric(4, foo(2)) checkEqualsNumeric(6, foo(2, nonexisting)) checkTrue(is.test(foo)) warning("This is a warning") cat("Youhou from test!\n") # Don't use, except for debugging! checkTrue(is.test(test(foo))) checkIdentical(attr(foo, "test"), test(foo)) checkException(foo(2, nonexisting)) #DEACTIVATED("My deactivation message") checkException(foo(2)) # This test fails } runTest(foo) # Now inspect the log, which is a 'svSuiteData' object is.svSuiteData(Log()) stats(Log()) metadata(Log()) Log() # Print method summary(Log()) ## Not run: # To get a print of the test protocol on file, use: protocol(Log(), type = "text", file = "RprofProtocol.out") file.show("RprofProtocol.out") unlink("RprofProtocol.out") ## End(Not run) rm(foo) ## Not run: # Profiling of very simple test runs library(utils) createLog(description = "test profiling", deleteExisting = TRUE) imax <- 3 jmax <- 100 l <- 50 Rprof() for (i in 1:imax) { # Change the context for these tests .Log$..Test <- paste("Test", i, sep = "") .Log$..Tag <- paste("#", i, sep = "") res <- system.time({ for (j in 1:jmax) checkTrue(i <= j, "My test") }, gcFirst = TRUE)[3] print(res) flush.console() } Rprof(NULL) # Look at profile summaryRprof() unlink("Rprof.out") # Look at the log summary(Log()) ## End(Not run)
clearLog() # Clear any existing log # Run some tests checkTrue(1 < 2) checkException(log("a")) foo <- function(x, y = 2) return(x * y) test(foo) <- function() { checkEqualsNumeric(4, foo(2)) checkEqualsNumeric(6, foo(2, nonexisting)) checkTrue(is.test(foo)) warning("This is a warning") cat("Youhou from test!\n") # Don't use, except for debugging! checkTrue(is.test(test(foo))) checkIdentical(attr(foo, "test"), test(foo)) checkException(foo(2, nonexisting)) #DEACTIVATED("My deactivation message") checkException(foo(2)) # This test fails } runTest(foo) # Now inspect the log, which is a 'svSuiteData' object is.svSuiteData(Log()) stats(Log()) metadata(Log()) Log() # Print method summary(Log()) ## Not run: # To get a print of the test protocol on file, use: protocol(Log(), type = "text", file = "RprofProtocol.out") file.show("RprofProtocol.out") unlink("RprofProtocol.out") ## End(Not run) rm(foo) ## Not run: # Profiling of very simple test runs library(utils) createLog(description = "test profiling", deleteExisting = TRUE) imax <- 3 jmax <- 100 l <- 50 Rprof() for (i in 1:imax) { # Change the context for these tests .Log$..Test <- paste("Test", i, sep = "") .Log$..Tag <- paste("#", i, sep = "") res <- system.time({ for (j in 1:jmax) checkTrue(i <= j, "My test") }, gcFirst = TRUE)[3] print(res) flush.console() } Rprof(NULL) # Look at profile summaryRprof() unlink("Rprof.out") # Look at the log summary(Log()) ## End(Not run)
The 'svTestData' contains results of test run. The checkxxx()
functions and
the runTest()
method generate one such object which is located in the
.Log
object in .GlobalEnv
. It is then possible to display and report
information it contains in various ways to analyze the results.
is.svTestData(x) stats(object, ...) ## S3 method for class 'svTestData' stats(object, ...) ## S3 method for class 'svTestData' print(x, all = FALSE, header = TRUE, file = "", append = FALSE, ...) ## S3 method for class 'svTestData' summary(object, header = TRUE, file = "", append = FALSE, ...) ## S3 method for class 'svTestData' protocol_junit(object, ...)
is.svTestData(x) stats(object, ...) ## S3 method for class 'svTestData' stats(object, ...) ## S3 method for class 'svTestData' print(x, all = FALSE, header = TRUE, file = "", append = FALSE, ...) ## S3 method for class 'svTestData' summary(object, header = TRUE, file = "", append = FALSE, ...) ## S3 method for class 'svTestData' protocol_junit(object, ...)
x |
Any kind of object, or a 'svTestData' object in the case of
|
object |
A 'svTestData' object. |
... |
Further arguments to pass to methods. Not used yet. |
all |
Do we print concise report for all test, or only for the tests that fail or produce an error? |
header |
Do we print a header or not? |
file |
Character. The path to the file where to write the report. If
|
append |
Do we append to this file? |
is.svTestData()
returns TRUE
if the object is an 'svTestData'. The
various methods serve to extract or print content in the object.
Philippe Grosjean
svTest()
, is.svSuiteData()
, Log()
, checkEquals()
foo <- function(x, y = 2) return(x * y) is.test(foo) # No # Create test cases for this function test(foo) <- function() { checkEqualsNumeric(4, foo(2)) checkEqualsNumeric(5, foo(2, 3)) checkEqualsNumeric(5, foo(nonexists)) } # Generate a 'svTestData' object by running the test obj <- runTest(foo) # Equivalent to runTest(test(foo)), but shorter obj summary(obj) stats(obj) is.svTestData(obj) rm(foo, obj)
foo <- function(x, y = 2) return(x * y) is.test(foo) # No # Create test cases for this function test(foo) <- function() { checkEqualsNumeric(4, foo(2)) checkEqualsNumeric(5, foo(2, 3)) checkEqualsNumeric(5, foo(nonexists)) } # Generate a 'svTestData' object by running the test obj <- runTest(foo) # Equivalent to runTest(test(foo)), but shorter obj summary(obj) stats(obj) is.svTestData(obj) rm(foo, obj)
Performs unit tests defined in this package by running
example(unitTests.svUnit)
. Tests are in runit*.R
files located in the
'/unitTests' subdirectory or one of its subdirectories ('/inst/unitTests' and
subdirectories in package sources).
Philippe Grosjean
if (require(svUnit)) { clearLog() runTest(svSuite("package:svUnit"), "svUnit") # Tests to run with example() but not with R CMD check runTest(svSuite("package:svUnit (VirtualClass)"), "VirtualClass") ## Not run: # Tests to present in ?unitTests.svUnit but not run automatically # Run all currently loaded packages test cases and test suites runTest(svSuiteList(), "AllTests") ## End(Not run) # Check errors at the end (needed to interrupt R CMD check) errorLog() }
if (require(svUnit)) { clearLog() runTest(svSuite("package:svUnit"), "svUnit") # Tests to run with example() but not with R CMD check runTest(svSuite("package:svUnit (VirtualClass)"), "VirtualClass") ## Not run: # Tests to present in ?unitTests.svUnit but not run automatically # Run all currently loaded packages test cases and test suites runTest(svSuiteList(), "AllTests") ## End(Not run) # Check errors at the end (needed to interrupt R CMD check) errorLog() }