Skip to content

Commit 21dbbc6

Browse files
committed
[enhancement] allow custom assertions in xqsuite tests
Add new functions test:fail#3 and test:fail#4 to XQSuite. Calling this function inside a XQSuite test function will stop execution by throwing a special error `test:failure`. This error is caught and handled as a failure allowing to create arbitrary custom assertions and the ability to provide specific error messages. Works in both XQuery and jUnit context. In jUnit you will only be presented with the serialized expected and actual values. For an example custom assertion see custom-assertion.xqm.
1 parent 8624469 commit 21dbbc6

File tree

2 files changed

+104
-0
lines changed

2 files changed

+104
-0
lines changed

exist-core/src/main/resources/org/exist/xquery/lib/xqsuite/xqsuite.xql

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,23 @@ declare function test:suite(
138138
</testsuites>
139139
};
140140

141+
declare function test:fail ($expected as item()*, $actual as item()*, $message as xs:string) as empty-sequence() {
142+
test:fail($expected, $actual, $message, "custom-assertion-failure")
143+
};
144+
145+
declare function test:fail (
146+
$expected as item()*,
147+
$actual as item()*,
148+
$message as xs:string,
149+
$type as xs:string
150+
) as empty-sequence() {
151+
error(xs:QName("test:failure"), $message, map {
152+
"expected": $expected,
153+
"actual": $actual,
154+
"type": $type
155+
})
156+
};
157+
141158
(:~
142159
: Find functions having the given annotation and call the callback function.
143160
:)
@@ -384,6 +401,32 @@ declare %private function test:test(
384401
else(),
385402
test:print-result($meta, $result, $assertResult)
386403
)
404+
} catch test:failure {
405+
(: when test:fail was called :)
406+
(: expected and actual can be of any type including functional ones :)
407+
let $serialized-expected := serialize($err:value?expected, map {"method": "adaptive"})
408+
let $serialized-actual := serialize($err:value?actual, map {"method": "adaptive"})
409+
410+
return (
411+
if (not(empty($test-failure-function))) then
412+
$test-failure-function(
413+
test:get-test-name($meta),
414+
(: expected :)
415+
map { "value": $serialized-expected },
416+
(: actual :)
417+
map { "result": $serialized-actual }
418+
)
419+
else ()
420+
,
421+
test:print-result(
422+
$meta,
423+
$serialized-actual,
424+
<report>
425+
<failure message="{ $err:description }" type="{$err:value?type}" />
426+
<output>{ $serialized-actual }</output>
427+
</report>
428+
)
429+
)
387430
} catch * {
388431
if ($assertError) then
389432
if (
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
xquery version "3.1";
2+
3+
(:~
4+
: Some tests on features of the test suite itself.
5+
:)
6+
module namespace ca="http://exist-db.org/xquery/test/xqsuite/custom-assertion";
7+
8+
import module namespace test="http://exist-db.org/xquery/xqsuite"
9+
at "resource:org/exist/xquery/lib/xqsuite/xqsuite.xql";
10+
11+
declare variable $ca:var := map {"a": 1, "b": 2};
12+
13+
declare
14+
%test:assertEquals("Key 'b' is missing", "map-assertion-failure")
15+
function ca:missing-key-default-type() as item()* {
16+
try {
17+
ca:map-assertion($ca:var, map {"a": 1, "c": 3})
18+
}
19+
catch test:failure {
20+
$err:description, $err:value?type
21+
}
22+
};
23+
24+
declare
25+
%test:assertEquals("Value mismatch for key 'b'", "custom-assertion-failure")
26+
function ca:wrong-value-custom-type() as item()* {
27+
try {
28+
ca:map-assertion($ca:var, map {"a": 1, "b": 3})
29+
}
30+
catch test:failure {
31+
$err:description, $err:value?type
32+
}
33+
};
34+
35+
declare
36+
%test:assertEquals("Type mismatch", "type-mismatch")
37+
function ca:type-mismatch-custom-type() as item()* {
38+
try {
39+
ca:map-assertion($ca:var, [1,2])
40+
}
41+
catch test:failure {
42+
$err:description, $err:value?type
43+
}
44+
};
45+
46+
declare %private
47+
function ca:map-assertion ($expected as map(*), $actual as item()*) as item()* {
48+
if (exists($actual) and count($actual) eq 1 and $actual instance of map(*))
49+
then (
50+
for-each(map:keys($expected), function ($key as xs:anyAtomicType) {
51+
if (not(map:contains($actual, $key)))
52+
then test:fail($expected, $actual, "Key '" || $key || "' is missing", "map-assertion-failure")
53+
else if ($expected($key) ne $actual($key))
54+
then test:fail($expected, $actual, "Value mismatch for key '" || $key || "'")
55+
else ()
56+
})
57+
,
58+
true()
59+
)
60+
else test:fail($expected, $actual, "Type mismatch", "type-mismatch")
61+
};

0 commit comments

Comments
 (0)