1 | #ifndef BANDIT_REPORTERS_XUNIT_REPORTER_H |
---|---|
2 | #define BANDIT_REPORTERS_XUNIT_REPORTER_H |
3 | |
4 | #include <iostream> |
5 | #include <bandit/reporters/progress_reporter.h> |
6 | |
7 | namespace bandit { |
8 | namespace detail { |
9 | struct xunit_reporter : public progress_reporter { |
10 | xunit_reporter(std::ostream& stm, const failure_formatter& formatter) |
11 | : progress_reporter(formatter), stm_(stm) {} |
12 | |
13 | xunit_reporter(const failure_formatter& formatter) |
14 | : xunit_reporter(std::cout, formatter) {} |
15 | |
16 | void it_starting(const std::string& desc) override { |
17 | progress_reporter::it_starting(desc); |
18 | work_stm_ << "\t<testcase classname=\""<< escape(current_context_name()) << "\" "; |
19 | work_stm_ << "name=\""<< escape(desc) << "\" time=\"0.0\">\n"; |
20 | } |
21 | |
22 | void it_succeeded(const std::string& desc) override { |
23 | progress_reporter::it_succeeded(desc); |
24 | work_stm_ << "\t</testcase>\n"; |
25 | } |
26 | |
27 | void it_failed(const std::string& desc, const assertion_exception& ex) override { |
28 | progress_reporter::it_failed(desc, ex); |
29 | work_stm_ << "\t\t<failure message=\""<< escape(failure_formatter_.format(ex)) << "\" />\n"; |
30 | work_stm_ << "\t</testcase>\n"; |
31 | } |
32 | |
33 | void it_unknown_error(const std::string& desc) override { |
34 | progress_reporter::it_unknown_error(desc); |
35 | work_stm_ << "\t\t<failure message=\"Unknown exception\" />\n"; |
36 | work_stm_ << "\t</testcase>\n"; |
37 | } |
38 | |
39 | void it_skip(const std::string& desc) override { |
40 | progress_reporter::it_skip(desc); |
41 | work_stm_ << "\t<testcase classname=\""<< escape(current_context_name()) << "\" "; |
42 | work_stm_ << "name=\""<< escape(desc) << "\" time=\"0.0\">\n"; |
43 | work_stm_ << "\t\t<skipped />\n"; |
44 | work_stm_ << "\t</testcase>\n"; |
45 | } |
46 | |
47 | void test_run_complete() override { |
48 | stm_ << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"; |
49 | stm_ << "<testsuite name=\"bandit\" tests=\""<< specs_run_ << "\" errors=\"0\" failures=\"" |
50 | << specs_failed_ << "\""; |
51 | |
52 | if (specs_skipped_ > 0) { |
53 | stm_ << " skipped=\""<< specs_skipped_ << "\""; |
54 | } |
55 | |
56 | stm_ << ">\n"; |
57 | |
58 | stm_ << work_stm_.str(); |
59 | |
60 | stm_ << "</testsuite>\n"; |
61 | } |
62 | |
63 | private: |
64 | std::string escape(const std::string& str) { |
65 | std::stringstream stm; |
66 | |
67 | for (char c : str) { |
68 | switch (c) { |
69 | case '&': |
70 | stm << "&"; |
71 | break; |
72 | case '<': |
73 | stm << "<"; |
74 | break; |
75 | case '>': |
76 | stm << ">"; |
77 | break; |
78 | case '\\': |
79 | stm << "'"; |
80 | break; |
81 | case '\"': |
82 | stm << """; |
83 | break; |
84 | default: |
85 | stm << c; |
86 | } |
87 | } |
88 | |
89 | return stm.str(); |
90 | } |
91 | |
92 | private: |
93 | std::ostream& stm_; |
94 | std::stringstream work_stm_; |
95 | }; |
96 | } |
97 | } |
98 | #endif |
99 |