Changes

Jump to navigation Jump to search
1,114 bytes added ,  13:15, 24 May 2018
no edit summary
This [[Module Library|XQuery Module]] contains annotations and functions for performing Unit XQUnit tests with XQuery.
=Introduction=
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, automatized automated way for of testing software. The [http://en.wikipedia.org/wiki/XUnit XUnit] frameworks (such as SUnit or JUnit) allow testing of atomic unit units of a program, such as single functions and algorithms.
This module borrows heavily from the existing frameworks: it introduces provides various new 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.
Please note that this module is still =Usage= Tests are started via the [[Commands#TEST|TEST]] command. It compiles all XQuery modules in beta stage, a given fileor directory and its functionality is still subject to changeruns all functions that are annotated with {{Code|%unit:test}}. Your feedback A test report is welcomegenerated and returned, which resembles the format returned by other xUnit testing frameworks,such as the Maven Surefire Plugin ([[#Result|see below]]).
=Conventions=
Both All annotations, functions and errors in this module are assigned to the {{Code|<code><nowiki>http://basex.org/modules/unit}} </nowiki></code> namespace, which is statically bound to the {{Code|unit}} prefix.<br/>
=Annotations=
|-
| width='120' | '''Syntax'''
|{{Code|%unit:test}}<br/>{{Code|%unit:test("expected", <ERROR>CODE)}}
|-
| '''Summary'''
|With this annotation, a function can be marked as unit test. It will be evaluated whenever if a test report is created for the module in which this function is located.<br/>If an optional <code>error </code > can be supplied as additional string argument. It is specified and if followed by <code>CODE</code>, which must be a valid [[XQuery 3.0#Expanded QNames|EQName]] string. If the function expression does not raise that error, the test will fail.|-| '''Examples'''|* The following test does will be successful, as it does nothing (and, hence, nothing wrong):<pre class="brush:xquery">declare %unit:test function local:void() { () };</pre>* The following test will be successful, as the function body will raise <code>err:XPTY0004</code>:<pre class="brush:xquery">declare %unit:test('expected', "err:XPTY0004") function local:add() { 123 + 'strings and integers cannot be added'};</pre>
|}
==%unit:before==
 
{| width='100%'
|-
| width='120' | '''Syntax'''
|{{Code|%unit:before}}<br/>{{Code|%unit:before(FUNCTION)}}
|-
| '''Summary'''
|A function decorated with this annotation will be evaluated '''before each''' unit test.<br/><code>FUNCTION</code> can be supplied as additional argument. It must be a valid [[XQuery 3.0#Expanded QNames|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'''|* The first function will be evaluated before the actual test:<pre class="brush:xquery">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'))};</pre>
|}
==%unit:after==
 
{| width='100%'
|-
| width='120' | '''Syntax'''
|{{Code|%unit:after}}<br/>{{Code|%unit:after(FUNCTION)}}
|-
| '''Summary'''
|A function decorated with this annotation will be evaluated '''after each''' unit test.<br/><code>FUNCTION</code> can be supplied as additional argument. It must be a valid [[XQuery 3.0#Expanded QNames|EQName]] string. If specified, the function will only be evaluated after a function with the given name is tested.
|}
|-
| width='120' | '''Syntax'''
|{{Code|%unit:ignore}}<br/>{{Code|%unit:ignore("message"MESSAGE)}}
|-
| '''Summary'''
|-
| width='120' | '''Signatures'''
|{{Func|unit:assert|$test as item()*|empty-sequence()}}<br />{{Func|unit:assert|$test as item()*, $message info as xs:stringitem()|empty-sequence()}}<br />
|-
| '''Summary'''
|Asserts that the effective boolean value of the specified {{Code|$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 {{Code|fn:boolean}} function.<br/>The unit default failure message can be overridden with the {{Code|$messageinfo}} stringargument.
|-
| '''Errors'''
|{{Error|UNIT0001fail|#Errors}} the assertion failed, or an error was raised.
|}
==unit:assert-equals==
 
{{Mark|Introduced with Version 7.8:}}
{| width='100%'
|-
| width='120' | '''Signatures'''
|{{Func|unit:assert-equals|$returned as item()*, $expected as item()*|empty-sequence()}}<br />{{Func|unit:assert-equals|$returned as item()*, $expected as item()*, $message info as xs:stringitem()|empty-sequence()}}<br />
|-
| '''Summary'''
|Asserts that the specified arguments are equal according to the rules of the [http://www.w3.org/TR/xpath-functions-30/#func-deep-equal {{Code|fn:deep-equalsequal}} function]. Otherwise, raises an error.<br/>The unit default failure message can be overridden with the {{Code|$messageinfo}} stringargument.
|-
| '''Errors'''
|{{Error|UNIT0001fail|#Errors}} the assertion failed, or an error was raised.
|}
==unit:fail==
{| width='100%'
|-
| width='120' | '''Signatures'''
|{{Func|unit:fail|$message as xs:string|empty-sequence()}}<br />
|-
| '''Summary'''
|Raises a unit error with the specified message.
|-
| '''Errors'''
|{{Error|UNIT0001|#Errors}} default error raised by this function.
|}
 
==unit:test==
 
{{Mark|Updated with Version 7.8:}} enhanced test report output
 
{| width='100%'
|-
| width='120' | '''Signatures'''
|{{Func|unit:test||element(testsuite)*}}<br />{{Func|unit:test|$functions as function(*)*|element(testsuite)*}}<br />
|-
| '''Summary'''
|Runs all functions, or the specified {{Code|$functions}}, in the current query context that have {{Code|unit}} annotations.<br />A test report is generated and returned, which resembles the format returned by other xUnit testing frameworks, such as the Maven Surefire Plugin.
|-
| '''Errors'''
|{{Error|UNIT0002|#Errors}} a test function must have no arguments.<br/>{{Error|UNIT0003|#Errors}} a test function must not be updating.<br/>{{Error|UNIT0004|#Errors}} an annotation was declared twice.<br/>{{Error|UNIT0005|#Errors}} an annotation has invalid arguments.
|-
| '''Examples'''
|{{Code|unit:test(inspect:context())}} runs all unit tests found in the query context.
|}
 
==unit:test-uris==
 
{{Mark|Updated with Version 7.8:}} enhanced test report output
{| width='100%'
|-
| width='120' | '''Signatures'''
|{{Func|unit:testfail||empty-urissequence()}}<br />{{Func|unit:fail|$uris info as xs:string*item()|elementempty-sequence(testsuites)}}<br />
|-
| '''Summary'''
|Runs all functions in Raises a unit error. The default failure message can be overridden with the specified modules that have {{Code|unit$info}} annotations.<br />A test report is generated and returned, which resembles the format returned by other xUnit testing frameworks, such as the Maven Surefire Pluginargument.
|-
| '''Errors'''
|{{Error|UNIT0002fail|#Errors}} a test default error raised by this function must have no arguments.<br/>{{Error|UNIT0003|#Errors}} a test function must not be updating.<br/>{{Error|UNIT0004|#Errors}} an annotation was declared twice.<br/>{{Error|UNIT0005|#Errors}} an annotation has invalid arguments.
|}
=Example=
The following XQuery main XQUnit module creates a test report{{Code|tests. It xqm}} contains all available unit annotations:
'''==Query:'''==
<pre class='brush:xquery'>
module namespace test = 'http://basex.org/modules/xqunit-tests';
 
(:~ Initializing function, which is called once before all tests. :)
declare %unit:before-module function unittest:before-all-tests() {
()
};
(:~ Initializing function, which is called once after all tests. :)
declare %unit:after-module function unittest:after-all-tests() {
()
};
(:~ Initializing function, which is called before each test. :)
declare %unit:before function unittest:before() {
()
};
(:~ Initializing function, which is called after each test. :)
declare %unit:after function unittest:after() {
()
};
(:~ Function demonstrating a successful test. :)
declare %unit:test function unittest:assert-success() {
unit:assert(<a/>)
};
(:~ Function demonstrating a failure using unit:assert. :)
declare %unit:test function unittest:assert-failure() {
unit:assert((), 'Empty sequence.')
};
(:~ Function demonstrating a failure using unit:assert-equals. :)
declare %unit:test function unittest:assert-equals-failure() {
unit:assert-equals(4 + 5, 6)
};
(:~ Function demonstrating an unexpected success. :)
declare %unit:test("expected", "err:FORG0001") function unittest:unexpected-success() {
()
};
(:~ Function demonstrating an expected failure. :)
declare %unit:test("expected", "err:FORG0001") function unittest:expected-failure() {
1 + <a/>
};
(:~ Function demonstrating the creation of a failure. :)
declare %unit:test function unittest:failure() {
unit:fail("Failure!")
};
(:~ Function demonstrating an error. :)
declare %unit:test function unittest:error() {
1 + <a/>
};
(:~ Skipping a test. :)
declare %unit:test %unit:ignore("Skipped!") function unittest:skipped() {
()
};
</pre>
By running {{Code|TEST tests.xqm}}, the following report will be generated (: run all tests :timings may differ)unit:test()</pre>
'''==Result:'''==
<pre class='brush:xml'>
<testsuites time="PT0.256S"> <testsuite name="file:///C:/Users/user/Desktop/xtest.xqxqm" time="PT0SPT0.212S" tests="8" failures="4" errors="1" skipped="1"> <testcase name="assert-success" time="PT0SPT0.016S"/> <testcase name="assert-failure" time="PT0SPT0.005S"> <failure line="2830" column="15" type="UNIT0001"> <info>Empty sequence.</info> </failure> </testcase> <testcase name="assert-equals-failure" time="PT0SPT0.006S"> <failure line="3335" 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="PT0SPT0.006S"> <failure> <expected>FORG0001</expected> </failure> </testcase> <testcase name="expected-failure" time="PT0SPT0.004S"/> <testcase name="failure" time="PT0SPT0.004S"> <failure line="4850" column="13" type="UNIT0001"> <info>Failure!</info> </failure> </testcase> <testcase name="error" time="PT0SPT0.004S"> <error line="5355" column="6" type="FORG0001">Invalid <info>Cannot cast to xs:double cast: "".</info> </error> </testcase> <testcase name="skipped" skipped="Skipped!" time="PT0S"/> </testsuite></testsuites>
</pre>
|Description
|-
|{{Code|UNIT0001fail}}
|An assertion failed, or an error was raised.
|-
|{{Code|UNIT0002no-args}}
|A test function must have no arguments.
|-
|{{Code|UNIT0003private}}|A test function must not be updating.|-|{{Code|UNIT0004}}|An annotation was declared twice.|-|{{Code|UNIT0005}}|An annotation has invalid argumentsprivate.
|}
=Changelog=
=Changelog=;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 * Deleted: {{Code|UNIT0006}} (ignore results returned by functions).* Added: [[#unit:fail|unit:fail]], 0-argument signature.* Updated: the info argument of functions can now be an arbitrary item.* Updated: infos are now represented in an <code>info</code> child element.* Updated: [[#unit:before|unit:before]] and [[#unit:after|unit:after]] can be extended by a filter argument. ;Version 7.9 * Added: TEST command* Removed: [[#unit:test|unit:test]], [[#unit:test-uris|unit:test-uris]]
;Version 7.8
 
* Added: [[#unit:assert-equals|unit:assert-equals]]
* Updated: enhanced test report output
This module was introduced with Version 7.7.
 
[[Category:XQuery]]
Bureaucrats, editor, reviewer, Administrators
13,550

edits

Navigation menu