This module contains annotations and functions for performing XQUnit tests.
The more complex a software application grows, the more error-prone it gets. This is why testing frameworks have been developed, which provide a standardized, automated way of testing software. The XUnit frameworks (such as SUnit or JUnit) allow testing of atomic units of a program, such as single functions and algorithms.
This module borrows heavily from the existing frameworks: it provides various annotations for testing XQuery functions. Unit functions are provided to assert the validity of arbitrary conditions expressed in XQuery and to raise errors whenever a condition is not satisfied. Some additional functions exist to run all unit tests of the current module or a set of specified library modules.
Tests are started via the TEST
command. It compiles all XQuery modules in a given file
or directory and runs all functions that are annotated with
%unit:test
. A test report is
generated and returned, which resembles the format returned by other xUnit testing frameworks,
such as the Maven Surefire Plugin (
see below).
All annotations, functions and errors in this module are assigned to the http://basex.org/modules/unit
namespace, which is statically bound to the unit
prefix.
Syntax | unit:test()
unit:test("expected", CODE)
|
---|
Summary | With this annotation, a function can be marked as unit test. It will be evaluated if a test report is created for the module in which this function is located. error can be supplied as additional string argument. It is followed by CODE , which must be a valid EQName string. If the function expression does not raise that error, the test will fail. |
---|
Examples | declare %unit:test function local:void() { () }; The following test will be successful, as it does nothing (and, hence, nothing wrong).
declare %unit:test('expected', "err:XPTY0004") function local:add() {
123 + 'strings and integers cannot be added'
}; The following test will be successful, as the function body will raise err:XPTY0004 . |
---|
Syntax | unit:before()
unit:before(FUNCTION)
|
---|
Summary | A function decorated with this annotation will be evaluated before each unit test as a separate transaction. FUNCTION can be supplied as additional argument. It must be a valid EQName string. If specified, the function will only be evaluated before a function with the given name is tested. This extension is e. g. helpful if the results of updates need to be tested. |
---|
Examples | declare %updating %unit:before("local:check") function local:before-check() {
db:create('test-db')
};
declare %updating %unit:test function local:check() {
unit:assert(db:exists('test-db'))
}; The first function will be evaluated before the actual test. |
---|
Syntax | unit:after()
unit:after(FUNCTION)
|
---|
Summary | A function decorated with this annotation will be evaluated after each unit test as a separate transaction. FUNCTION can be supplied as additional argument. It must be a valid EQName string. If specified, the function will only be evaluated after a function with the given name is tested. |
---|
Syntax | unit:before-module()
|
---|
Summary | If a function is decorated with this annotation, it will be evaluated before all unit tests in the current module as a separate transaction. |
---|
Syntax | unit:after-module()
|
---|
Summary | If a function is decorated with this annotation, it will be evaluated after all unit tests in the current module as a separate transaction. |
---|
Syntax | unit:ignore()
unit:ignore(MESSAGE)
|
---|
Summary | If a function is decorated with this annotation, it will temporarily be ignored by the test suite runner. |
---|
Signature | unit:assert(
$test as item()*,
$info as item() := ()
) as empty-sequence() |
---|
Summary | Asserts that the effective boolean value of the specified $test is true and returns an empty sequence. Otherwise, raises an error. The effective boolean value of an expression can be explicitly computed by using the fn:boolean function. The default failure message can be overridden with the $info argument. |
---|
Errors | fail | An assertion failed, or an error was raised. |
|
---|
Signature | unit:assert-equals(
$returned as item()*,
$expected as item()*,
$info as item() := ()
) as empty-sequence() |
---|
Summary | Asserts that the specified arguments are equal according to the rules of the fn:deep-equal function. Otherwise, raises an error. The default failure message can be overridden with the $info argument. |
---|
Errors | fail | An assertion failed, or an error was raised. |
|
---|
Signature | unit:fail(
$info as item() := ()
) as empty-sequence() |
---|
Summary | Raises a unit error. The default failure message can be overridden with the $info argument. |
---|
Errors | fail | An assertion failed, or an error was raised. |
|
---|
The following XQUnit module tests.xqm
contains all available unit annotations:
module namespace test = 'http://basex.org/modules/xqunit-tests';
(:~ Initializing function, which is called once before all tests. :)
declare %unit:before-module function test:before-all-tests() {
()
};
(:~ Initializing function, which is called once after all tests. :)
declare %unit:after-module function test:after-all-tests() {
()
};
(:~ Initializing function, which is called before each test. :)
declare %unit:before function test:before() {
()
};
(:~ Initializing function, which is called after each test. :)
declare %unit:after function test:after() {
()
};
(:~ Function demonstrating a successful test. :)
declare %unit:test function test:assert-success() {
unit:assert(<a/>)
};
(:~ Function demonstrating a failure using unit:assert. :)
declare %unit:test function test:assert-failure() {
unit:assert((), 'Empty sequence.')
};
(:~ Function demonstrating a failure using unit:assert-equals. :)
declare %unit:test function test:assert-equals-failure() {
unit:assert-equals(4 + 5, 6)
};
(:~ Function demonstrating an unexpected success. :)
declare %unit:test("expected", "err:FORG0001") function test:unexpected-success() {
()
};
(:~ Function demonstrating an expected failure. :)
declare %unit:test("expected", "err:FORG0001") function test:expected-failure() {
1 + <a/>
};
(:~ Function demonstrating the creation of a failure. :)
declare %unit:test function test:failure() {
unit:fail("Failure!")
};
(:~ Function demonstrating an error. :)
declare %unit:test function test:error() {
1 + <a/>
};
(:~ Skipping a test. :)
declare %unit:test %unit:ignore("Skipped!") function test:skipped() {
()
};
By running TEST tests.xqm
, the following report will be generated (timings may differ):
<testsuites time="PT0.256S">
<testsuite name="file:///C:/Users/user/Desktop/test.xqm"
time="PT0.212S" tests="8" failures="4" errors="1" skipped="1">
<testcase name="assert-success" time="PT0.016S"/>
<testcase name="assert-failure" time="PT0.005S">
<failure line="30" column="15">
<info>Empty sequence.</info>
</failure>
</testcase>
<testcase name="assert-equals-failure" time="PT0.006S">
<failure line="35" column="22">
<returned item="1" type="xs:integer">9</returned>
<expected item="1" type="xs:integer">6</expected>
<info>Item 1: 6 expected, 9 returned.</info>
</failure>
</testcase>
<testcase name="unexpected-success" time="PT0.006S">
<failure>
<expected>FORG0001</expected>
</failure>
</testcase>
<testcase name="expected-failure" time="PT0.004S"/>
<testcase name="failure" time="PT0.004S">
<failure line="50" column="13">
<info>Failure!</info>
</failure>
</testcase>
<testcase name="error" time="PT0.004S">
<error line="55" column="6" type="FORG0001">
<info>Cannot cast to xs:double: "".</info>
</error>
</testcase>
<testcase name="skipped" skipped="Skipped!" time="PT0S"/>
</testsuite>
</testsuites>
Code | Description |
---|
fail | An assertion failed, or an error was raised. |
no-args | A test function must have no arguments. |
private | A test function must not be private. |
Version 9.0- Updated: error codes updated; errors now use the module namespace
Version 8.0.2- Updated: (expected) errors are compared by QNames instead of local names (including namespaces).
Version 8.0- Added:
unit:fail
, 0-argument signature. - Updated: the info argument of functions can now be an arbitrary item.
- Updated: infos are now represented in an
info
child element. - Updated:
unit:before
and unit:after
can be extended by a filter argument. - Deleted:
UNIT0006
(ignore results returned by functions).
Version 7.9- Added: TEST command
- Removed:
unit:test
, unit:test-uris
Version 7.8Version 7.7