Skip to content

Commit 11947fa

Browse files
committed
Merge branch 'alt-report-formats' of https://github.com/jonesyface/ml-unit-test into jonesyface-alt-report-formats
2 parents 47a898c + 98f710a commit 11947fa

File tree

5 files changed

+182
-26
lines changed

5 files changed

+182
-26
lines changed

src/main/ml-modules/root/test/default.xqy

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ declare function local:run() {
3434
if ($suite) then
3535
let $result := helper:run-suite($suite, $tests, $run-suite-teardown, $run-teardown, $calculate-coverage)
3636
return
37-
if ($format eq "junit") then
38-
helper:format-junit($result)
37+
if ($format) then
38+
helper:format($result, $format, $suite)
3939
else
4040
$result
4141
else ()
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<!--
2+
Convert default ml-uni-test report XML output to valid JUnit report XML
3+
-->
4+
<xsl:stylesheet version="2.0"
5+
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
6+
xmlns:t="http://marklogic.com/roxy/test"
7+
xmlns:error="http://marklogic.com/xdmp/error"
8+
exclude-result-prefixes="#all">
9+
<xsl:output method="xml" encoding="utf-8" indent="yes"/>
10+
11+
<!-- Required inputs -->
12+
<xsl:param name="hostname"/>
13+
<xsl:param name="timestamp"/>
14+
15+
<!-- Output all text nodes, elements and attributes -->
16+
<xsl:template match="@*|node()">
17+
<xsl:copy>
18+
<xsl:apply-templates select="@*|node()" />
19+
</xsl:copy>
20+
</xsl:template>
21+
22+
<!-- Output test suites -->
23+
<xsl:template match="t:suite">
24+
<testsuite errors="0" failures="{@failed}" hostname="{$hostname}" name="{@name}" tests="{@total}" time="{@time}" timestamp="{$timestamp}">
25+
<xsl:apply-templates/>
26+
</testsuite>
27+
</xsl:template>
28+
29+
<!-- Output test cases within test suites -->
30+
<xsl:template match="t:test">
31+
<testcase classname="{@name}" name="{@name}" time="{@time}">
32+
<xsl:apply-templates/>
33+
</testcase>
34+
</xsl:template>
35+
36+
<!-- Output test case failures -->
37+
<xsl:template match="t:result[@type = 'fail']">
38+
<failure type="{error:error/error:name/string()}" message="{error:error/error:message/string()}">
39+
<xsl:apply-templates mode="serialize"/>
40+
</failure>
41+
</xsl:template>
42+
43+
<!-- Prevent output test case successes -->
44+
<xsl:template match="t:result[@type = 'success']"/>
45+
46+
<!-- Serialize error stack output so document is valid JUnit XML -->
47+
<xsl:template match="*" mode="serialize">
48+
<xsl:text>&lt;</xsl:text>
49+
<xsl:value-of select="name()"/>
50+
<xsl:apply-templates select="@*" mode="serialize" />
51+
<xsl:if test="name() = 'error:error'">
52+
<xsl:for-each select="namespace::*">
53+
<xsl:text> </xsl:text>
54+
<xsl:value-of select="name()"/>
55+
<xsl:text>="</xsl:text>
56+
<xsl:value-of select="."/>
57+
<xsl:text>"</xsl:text>
58+
</xsl:for-each>
59+
</xsl:if>
60+
<xsl:choose>
61+
<xsl:when test="node()">
62+
<xsl:text>&gt;</xsl:text>
63+
<xsl:apply-templates mode="serialize" />
64+
<xsl:text>&lt;/</xsl:text>
65+
<xsl:value-of select="name()"/>
66+
<xsl:text>&gt;</xsl:text>
67+
</xsl:when>
68+
<xsl:otherwise>
69+
<xsl:text> /&gt;</xsl:text>
70+
</xsl:otherwise>
71+
</xsl:choose>
72+
</xsl:template>
73+
74+
<xsl:template match="@*" mode="serialize">
75+
<xsl:text> </xsl:text>
76+
<xsl:value-of select="name()"/>
77+
<xsl:text>="</xsl:text>
78+
<xsl:value-of select="."/>
79+
<xsl:text>"</xsl:text>
80+
</xsl:template>
81+
82+
<xsl:template match="text()" mode="serialize">
83+
<xsl:value-of select="."/>
84+
</xsl:template>
85+
86+
</xsl:stylesheet>

src/main/ml-modules/root/test/test-controller.xqy

Lines changed: 89 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@ import module namespace helper = "http://marklogic.com/roxy/test-helper" at "/te
1414
declare namespace t="http://marklogic.com/roxy/test";
1515

1616
declare variable $FS-PATH as xs:string := if (xdmp:platform() eq "winnt") then "\" else "/";
17-
1817
declare variable $TEST-SUITES-ROOT := "/test/suites/";
18+
declare variable $db-id as xs:unsignedLong := xdmp:modules-database();
19+
declare variable $root as xs:string := xdmp:modules-root();
20+
1921

2022
(:
2123
: Returns a list of the available tests. This list is magically computed based on the modules
@@ -29,45 +31,89 @@ declare function list()
2931
)
3032
return
3133
element t:tests {
32-
let $db-id as xs:unsignedLong := xdmp:modules-database()
33-
let $root as xs:string := xdmp:modules-root()
3434
let $suites as xs:string* :=
3535
if ($db-id = 0) then
3636
xdmp:filesystem-directory(fn:concat($root, $FS-PATH, "test/suites"))/dir:entry[dir:type = "directory" and fn:not(dir:filename = $suite-ignore-list)]/dir:filename
3737
else
38-
let $uris := helper:list-from-database($db-id, $root, ())
38+
let $uris := helper:list-from-database($db-id, $root, (), 'suites')
3939
return
4040
fn:distinct-values(
4141
for $uri in $uris
4242
let $path := fn:replace(cvt:basepath($uri), fn:concat($root, "test/suites/?"), "")
4343
where $path ne "" and fn:not(fn:contains($path, "/")) and fn:not($path = $suite-ignore-list)
4444
return
4545
$path)
46-
for $suite as xs:string in $suites
47-
let $tests as xs:string* :=
46+
let $main-formats as xs:string* :=
4847
if ($db-id = 0) then
49-
xdmp:filesystem-directory(fn:concat($root, $FS-PATH, "test/suites/", $suite))/dir:entry[dir:type = "file" and fn:not(dir:filename = $test-ignore-list)]/dir:filename[fn:ends-with(., ".xqy") or fn:ends-with(., ".sjs")]
48+
xdmp:filesystem-directory(fn:concat($root, $FS-PATH, "test/formats"))/dir:entry[dir:type = "file" and fn:not(dir:filename = $test-ignore-list)]/dir:filename[fn:ends-with(., ".xsl")]
5049
else
51-
let $uris := helper:list-from-database($db-id, $root, fn:concat($suite, '/'))
50+
let $uris := helper:list-from-database($db-id, $root, (), 'formats')
5251
return
5352
fn:distinct-values(
5453
for $uri in $uris
55-
let $path := fn:replace($uri, fn:concat($root, "test/suites/", $suite, "/"), "")
56-
where $path ne "" and fn:not(fn:contains($path, "/")) and fn:not($path = $test-ignore-list) and (fn:ends-with($path, ".xqy") or fn:ends-with($path, ".sjs"))
54+
let $path := fn:replace($uri, fn:concat($root, "test/formats/"), "")
55+
where $path ne "" and fn:not(fn:contains($path, "/")) and fn:not($path = $test-ignore-list) and (fn:ends-with($path, ".xsl"))
5756
return
5857
$path)
59-
where $tests
60-
return
61-
element t:suite {
62-
attribute path {$suite},
63-
element t:tests {
64-
for $test in $tests
58+
return (
59+
for $suite as xs:string in $suites
60+
let $tests as xs:string* :=
61+
if ($db-id = 0) then
62+
xdmp:filesystem-directory(fn:concat($root, $FS-PATH, "test/suites/", $suite))/dir:entry[dir:type = "file" and fn:not(dir:filename = $test-ignore-list)]/dir:filename[fn:ends-with(., ".xqy") or fn:ends-with(., ".sjs")]
63+
else
64+
let $uris := helper:list-from-database(
65+
$db-id, $root, fn:concat($suite, '/'), 'suites')
66+
return
67+
fn:distinct-values(
68+
for $uri in $uris
69+
let $path := fn:replace($uri, fn:concat($root, "test/suites/", $suite, "/"), "")
70+
where $path ne "" and fn:not(fn:contains($path, "/")) and fn:not($path = $test-ignore-list) and (fn:ends-with($path, ".xqy") or fn:ends-with($path, ".sjs"))
71+
return
72+
$path)
73+
let $formats as xs:string* :=
74+
if ($db-id = 0) then
75+
xdmp:filesystem-directory(fn:concat($root, $FS-PATH, "test/suites/", $suite, "/formats"))/dir:entry[dir:type = "file" and fn:not(dir:filename = $test-ignore-list)]/dir:filename[fn:ends-with(., ".xsl")]
76+
else
77+
let $uris := helper:list-from-database(
78+
$db-id, $root, fn:concat($suite, '/formats/'), 'suites')
79+
return
80+
fn:distinct-values(
81+
for $uri in $uris
82+
let $path := fn:replace($uri, fn:concat($root, "test/suites/", $suite, "/formats/"), "")
83+
where $path ne "" and fn:not(fn:contains($path, "/")) and fn:not($path = $test-ignore-list) and (fn:ends-with($path, ".xsl"))
84+
return
85+
$path)
86+
where $tests
87+
return
88+
element t:suite {
89+
attribute path {$suite},
90+
element t:tests {
91+
for $test in $tests
92+
return
93+
element t:test {
94+
attribute path {$test}
95+
}
96+
},
97+
if ($formats) then
98+
element t:formats {
99+
for $format in $formats
100+
return
101+
element t:format {
102+
attribute path {$format}
103+
}
104+
}
105+
else ()
106+
},
107+
if ($main-formats) then
108+
element t:formats {
109+
for $main-format in $main-formats
65110
return
66-
element t:test {
67-
attribute path {$test}
111+
element t:format {
112+
attribute path {$main-format}
68113
}
69114
}
70-
}
115+
else ()
116+
)
71117
}
72118
};
73119

@@ -98,7 +144,7 @@ declare function run-suite(
98144
$run-suite-teardown as xs:boolean,
99145
$run-teardown as xs:boolean)
100146
{
101-
run-suite($suite, $tests, $run-suite-teardown, $run-teardown, fn:false())
147+
run-suite($suite, $tests, $run-suite-teardown, $run-teardown, fn:false())
102148
};
103149

104150
(:~
@@ -205,6 +251,29 @@ declare function run(
205251
};
206252

207253

254+
declare function format($result as element(), $format as xs:string, $suite as xs:string)
255+
{
256+
if ($format eq "junit") then
257+
format-junit($suite)
258+
else
259+
let $format-uris := helper:list-from-database($db-id, $root, (), 'formats')
260+
let $suite-format-uris := helper:list-from-database($db-id, $root, $suite || '/formats/', 'suites')
261+
let $xsl-match :=
262+
for $uri in ($format-uris, $suite-format-uris)
263+
return
264+
if (fn:matches(fn:tokenize($uri, '/')[fn:last()], '^' || $format || '(\.xsl)?$')) then $uri
265+
else ()
266+
return
267+
if ($xsl-match) then
268+
let $xsl := $xsl-match[1]
269+
let $params := map:map()
270+
let $_ := map:put($params, "hostname", fn:tokenize(xdmp:get-request-header("Host"), ":")[1])
271+
let $_ := map:put($params, "timestamp", fn:current-dateTime())
272+
return xdmp:xslt-invoke($xsl, $result, $params)/element()
273+
else $result
274+
};
275+
276+
208277
declare function format-junit($suite as element())
209278
{
210279
element testsuite {

src/main/ml-modules/root/test/test-helper.xqy

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,8 @@ declare function helper:log($items as item()*)
556556
declare function helper:list-from-database(
557557
$database as xs:unsignedLong,
558558
$root as xs:string,
559-
$suite as xs:string?)
559+
$suite as xs:string?,
560+
$file-type as xs:string)
560561
as xs:string*
561562
{
562563
xdmp:eval(
@@ -567,7 +568,7 @@ as xs:string*
567568
if ($ex/error:code ne "XDMP-URILXCNNOTFOUND") then xdmp:rethrow()
568569
else xdmp:directory($PATH, "infinity")/xdmp:node-uri(.) }',
569570
(xs:QName('PATH'),
570-
fn:concat($root, 'test/suites/', ($suite, '')[1])),
571+
fn:concat($root, 'test/', $file-type, '/', ($suite, '')[1])),
571572
<options xmlns="xdmp:eval"><database>{$database}</database></options>)
572573
};
573574

src/main/ml-modules/services/ml-unit-test.xqy

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ declare private function run($params as map:map)
3838
if ($suite) then
3939
let $result := helper:run-suite($suite, $tests, $run-suite-teardown, $run-teardown)
4040
return
41-
if ($format eq "junit") then
42-
helper:format-junit($result)
41+
if ($format) then
42+
helper:format($result, $format, $suite)
4343
else
4444
$result
4545
else ()

0 commit comments

Comments
 (0)