├── LICENSE ├── README.md ├── sample_xunit_report.xml ├── saxon9he.jar ├── usage.gif └── xunit_to_html.xsl /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Muntazir Fadhel 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # :rocket: xunit-to-html 2 | 3 | 4 | [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com) 5 | [![Open Source Love](https://badges.frapsoft.com/os/v2/open-source.svg?v=103)](https://github.com/ellerbrock/open-source-badges/) 6 | [![MIT Licence](https://badges.frapsoft.com/os/mit/mit.svg?v=103)](https://opensource.org/licenses/mit-license.php) 7 | 8 | **xunit-to-html** converts xUnit XML reports into beautiful looking HTML reports using XSLT. 9 | 10 | ![usage](/usage.gif) 11 | 12 | # Supported Frameworks 13 | xunit-to-html can be used to generate beautiful looking reports from any xUnit supported test framework, including the following ones: 14 | * JUnit (supported schema are Ant junit and Maven Surefire) 15 | * AUnit 16 | * MSTest (imported from MSTest Plugin) 17 | * NUnit (imported from NUnit Plugin) 18 | * UnitTest++ 19 | * Boost Test Library 20 | * PHPUnit 21 | * Free Pascal Unit 22 | * CppUnit 23 | * MbUnit 24 | * Googletest 25 | * EmbUnit 26 | * gtester/glib 27 | * QTestLib 28 | * nosetests 29 | 30 | # Prerequisites 31 | 1. Environment with Java 8+ installed 32 | 2. The open source [Saxon](http://saxon.sourceforge.net/) Home Edition jar which has been included in this repository. 33 | 34 | # Installing and Getting Started 35 | 36 | **xunit-to-html** can be easily be used as part of a build pipeline to produce beautiful looking test reports. 37 | 38 | 1. Clone this repository 39 | 2. Run your tests and generate an xUnit XML report using a test framework of your choice. 40 | 3. Assuming the input xUnit report name is `report.xml`, and we want to generate an html report `report.html`: 41 | ```bash 42 | java -jar saxon9he.jar -o:report.html -s:report.xml -xsl:xunit_to_html.xsl 43 | ``` 44 | `report.html` will be generated in the working directory, you can now view or push the report to the cloud for further visibility. 45 | 46 | # Authors 47 | 48 | - [**Muntazir Fadhel**](https://zir0-93.github.io/) - *Initial work and maintainer* 49 | -------------------------------------------------------------------------------- /sample_xunit_report.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Traceback (most recent call last): 7 | File "nose2/tests/functional/support/scenario/tests_in_package/pkg1/test/test_things.py", line 17, in test_failed 8 | assert False, "I failed" 9 | AssertionError: I failed 10 | 11 | 28 | 29 | 30 | 31 | 32 | Traceback (most recent call last): 33 | File "nose2/plugins/loader/parameters.py", line 144, in _method 34 | return method(self, *argSet) 35 | File "nose2/tests/functional/support/scenario/tests_in_package/pkg1/test/test_things.py", line 29, in test_params_method 36 | self.assertEqual(a, 1) 37 | AssertionError: 2 != 1 38 | 39 | 56 | 57 | 58 | 59 | 60 | 61 | Traceback (most recent call last): 62 | File "nose2/tests/functional/support/scenario/tests_in_package/pkg1/test/test_things.py", line 13, in test_typeerr 63 | raise TypeError("oops") 64 | TypeError: oops 65 | 66 | 83 | 84 | 85 | 86 | Traceback (most recent call last): 87 | File "nose2/plugins/loader/generators.py", line 145, in method 88 | return func(*args) 89 | File "nose2/tests/functional/support/scenario/tests_in_package/pkg1/test/test_things.py", line 24, in check 90 | assert x == 1 91 | AssertionError 92 | 93 | 110 | 111 | -------------------------------------------------------------------------------- /saxon9he.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zir0-93/xunit-to-html/ec91c445a6beb389bfb9ba2c92fcdc35b43e926e/saxon9he.jar -------------------------------------------------------------------------------- /usage.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zir0-93/xunit-to-html/ec91c445a6beb389bfb9ba2c92fcdc35b43e926e/usage.gif -------------------------------------------------------------------------------- /xunit_to_html.xsl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 38 | 39 | 40 | 42 | 44 | 46 | 48 | 49 | 50 |
51 |

52 |
53 | 54 | 55 | Test 56 | 57 | Result 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 | Tests 86 |
87 |
88 |
89 |
90 | 91 | 92 | 93 | 94 |
95 |
96 | Passed 97 |
98 |
99 |
100 |
101 | 102 | 103 | 104 | 105 |
106 |
107 | Failed 108 |
109 |
110 |
111 |
112 | 113 | 114 | 115 | 116 |
117 |
118 | Errored 119 |
120 |
121 |
122 |
123 | 124 | 125 | 126 | 127 | 128 | min 129 | 130 |
131 |
132 | Runtime 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 | sec 169 |
170 |
171 | 172 | Test Suite 173 | 174 |
175 | 176 | 177 | 178 |
179 | 180 | 181 | 182 | 183 | 184 | 185 | failed 186 |
187 |
188 |
189 | 190 | 191 |
192 | 193 | 194 | 195 | 196 | 197 | 198 | errored 199 |
200 |
201 |
202 | 203 | 204 |
205 | 206 | 207 | 208 | 209 | 210 | 211 | passed 212 |
213 |
214 |
215 | 216 | 217 | 218 |
219 | 220 | 221 | 222 | 223 | 224 | 225 | skipped 226 |
227 |
228 |
229 |
230 | 231 | 232 | 233 | 234 |
235 | 236 | 237 | 238 | 239 |
240 |
241 |
242 |
243 |
244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 |
258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 |
266 | 267 | 268 | 269 | 270 | 271 | 272 | sec 273 |
274 |
275 | 276 | Test Class 277 | 278 |
279 | 280 | 281 | 282 |
283 | 284 | 285 | 286 | 287 | 288 | 289 | skipped 290 |
291 |
292 |
293 | 294 | 295 | 296 |
297 | 298 | 299 | 300 | 301 | 302 | 303 |
304 |
305 | 306 |
307 | 308 | 309 | 310 | 311 | 312 | 313 |
314 |
315 |
316 | 317 | 318 |
319 | 320 | 321 | 322 | 323 | 324 | 325 |
326 |
327 |
328 |
329 | 330 | 331 | 332 | 333 |
334 | 335 | 336 | 337 | 338 |
339 |
340 |
341 |
342 |
343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | cursor:default; 351 | 352 | 353 |
354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 |
385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | ~ 0 393 | 394 | sec 395 | 396 | 397 | 398 | 399 | 400 | 401 | sec 402 | 403 | 404 |
405 | 406 | 407 |
408 | 409 | 410 | 411 | 412 |
413 |
414 | 415 |
416 | 417 | 418 | 419 | 420 |
421 |
422 |
423 |
424 | 425 | 426 | 427 | 428 |
429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 |
446 | 447 | 448 |

449 | 450 | 451 | ... 452 |

453 |
454 | 455 |

456 | 457 | 458 |

459 |
460 |
461 | 462 | 463 |

464 | 465 | ... 466 |

467 |
468 | 469 |

470 | 471 | 472 |

473 |
474 |
475 |
476 | 552 | 553 | 554 |
555 | 556 | 557 | 558 | 559 |
560 | 								            								
561 | 								            							
562 |
563 |
564 |
565 | 566 | 567 |
568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | ui tab active 576 | 577 | 578 | ui tab 579 | 580 | 581 | 582 |
583 | 									            							
584 | 									            						
585 |
586 |
587 |
588 | 589 | 590 |
591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | ui tab active 599 | 600 | 601 | ui tab 602 | 603 | 604 | 605 |
606 | 								            								
607 | 								            							
608 |
609 |
610 |
611 | 612 | 613 |
614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | ui tab active 622 | 623 | 624 | ui tab 625 | 626 | 627 | 628 |
629 | 							            										
630 | 							            									
631 |
632 |
633 |
634 |
635 |
636 |
637 |
638 | 639 |
640 |
641 |
642 |
643 |
644 |
645 |
646 |
647 |
648 |
649 |
650 |
651 |
652 | 658 | 659 | 660 |
661 |
--------------------------------------------------------------------------------