Create and run test suites by collecting together unit tests and function tests defined in objects

Share:

Description

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.

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 lised 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.

Usage

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
svSuite(tests)

as.svSuite(x)
is.svSuite(x)

svSuiteList(packages = TRUE, objects = TRUE, dirs = getOption("svUnit.dirs"),
	excludeList = getOption("svUnit.excludeList"), pos = .GlobalEnv,
	loadPackages = FALSE)

## S3 method for class 'svSuite'
print(x, ...)
## 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, ...)

Arguments

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.

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 "package:MYPKG" will exclude all items from package 'MYPKG', while using "package:MYPKG$" will exclude only tests suites defined in the .../MYPKG/unitTests directory, bur not in its subdirectories. For convenience, it can be saved in a 'svUnit.excludeList' option. By default, all tests for packages whose name start with 'sv' or 'RUnit' are excluded, that is, c("package:sv", "package:RUnit").

pos

the environment to look for 'objects' (environment, character string with name of an environment, or interger with position of the environment in the search path.

loadPackages

in the case a list of packages is provided in packages =, do we make sure that these packages are loaded? If yes, the function will try to load all packages in that list that are not loaded yet and will issue a warning for the packages not found. Default, FALSE.

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 .setUp() function in your unit file (this function is executed before each test.

codeTearDown

an expression with some code you want to add to the .tearDown() function in your unit file (this function is executed after each test.

unitname

the name of a unit to run inside the suite. If NULL (by default), all units are run.

...

further arguments to pass to makeUnit() or runTest() (not used yet).

Details

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 loosy 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 loosy 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")).

Value

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() run 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.

Author(s)

Philippe Grosjean <phgrosjean@sciviews.org>

See Also

svSuiteData, svTest, Log, check, checkTrue

Examples

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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 loosely 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)