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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
open Tyxml.Xml
type token = string
type timestamp = string
let timestamp time =
let (y, m, d), ((hh, ss, mm), _) = Ptime.to_date_time time in
Printf.sprintf "%04d-%02d-%02dT%02d:%02d:%02d" y m d hh ss mm
;;
type property =
{ name : token
; value : string
}
type properties = property list
let property ~name ~value = { name; value }
let property_to_xml property =
let name = string_attrib "name" property.name in
let value = string_attrib "value" property.value in
node "property" ~a:[ name; value ] []
;;
let properties_to_xml properties = node "properties" (List.map property_to_xml properties)
type error =
{ message : string option
; typ : string
; description : string
}
let error ?message ~typ description : error = { message; typ; description }
let error_to_xml (error : error) =
let typ = string_attrib "type" error.typ in
let attributes = [ typ ] in
let attributes =
match error.message with
| None -> attributes
| Some m ->
let message = string_attrib "message" m in
message :: attributes
in
let description = pcdata error.description in
node "error" ~a:attributes [ description ]
;;
type failure =
{ message : string option
; typ : string
; description : string
}
let failure ?message ~typ description : failure = { message; typ; description }
let failure_to_xml (failure : failure) =
let typ = string_attrib "type" failure.typ in
let attributes = [ typ ] in
let attributes =
match failure.message with
| None -> attributes
| Some m ->
let message = string_attrib "message" m in
message :: attributes
in
let description = pcdata failure.description in
node "failure" ~a:attributes [ description ]
;;
type result =
| Error of error
| Failure of failure
| Pass
| Skipped
let result_to_xml : result -> Tyxml.Xml.elt = function
| Error e -> error_to_xml e
| Failure f -> failure_to_xml f
| Pass -> Tyxml.Xml.empty ()
| Skipped -> node "skipped" []
;;
type testcase =
{ name : string
; classname : token
; time : float
; result : result
}
type testcases = testcase list
let testcase ~name ~classname ~time result = { name; classname; time; result }
let testcase_to_xml (testcase : testcase) =
let name = string_attrib "name" testcase.name in
let classname = string_attrib "classname" testcase.classname in
let time = float_attrib "time" testcase.time in
let result = result_to_xml testcase.result in
node "testcase" ~a:[ name; classname; time ] [ result ]
;;
type testsuite =
{ package : token
; id : int
; name : token
; timestamp : timestamp
; hostname : token
; tests : int
; failures : int
; errors : int
; skipped : int
; time : float
; properties : properties
; testcases : testcases
; system_out : string option
; system_err : string option
}
type testsuites = testsuite list
let testsuite
?system_out
?system_err
~package
~id
~name
~timestamp
~hostname
~tests
~failures
~errors
~skipped
~time
properties
testcases
=
{ package
; id
; name
; timestamp
; hostname
; tests
; failures
; errors
; skipped
; time
; properties
; testcases
; system_out
; system_err
}
;;
let testsuite_to_xml testsuite =
let package = string_attrib "package" testsuite.package in
let id = int_attrib "id" testsuite.id in
let name = string_attrib "name" testsuite.name in
let timestamp = string_attrib "timestamp" testsuite.timestamp in
let hostname = string_attrib "hostname" testsuite.hostname in
let tests = int_attrib "tests" testsuite.tests in
let failures = int_attrib "failures" testsuite.failures in
let errors = int_attrib "errors" testsuite.errors in
let skipped = int_attrib "skipped" testsuite.skipped in
let time = float_attrib "time" testsuite.time in
let attributes =
[ package; id; name; timestamp; hostname; tests; failures; errors; skipped; time ]
in
let system_out =
match testsuite.system_out with
| None -> empty ()
| Some so -> node "system_out" [ pcdata so ]
in
let system_err =
match testsuite.system_err with
| None -> empty ()
| Some se -> node "system_err" [ pcdata se ]
in
let properties = properties_to_xml testsuite.properties in
let testcases = List.map testcase_to_xml testsuite.testcases in
node "testsuite" ~a:attributes (properties :: system_out :: system_err :: testcases)
;;
let to_xml testsuites =
let elements = List.map testsuite_to_xml testsuites in
node "testsuites" elements
;;