]> git.stg.codes - stg.git/blobdiff - tests/tut/tut_cppunit_reporter.hpp
Додано заголовочні файлі фреймворка для unit-тестування TUT
[stg.git] / tests / tut / tut_cppunit_reporter.hpp
diff --git a/tests/tut/tut_cppunit_reporter.hpp b/tests/tut/tut_cppunit_reporter.hpp
new file mode 100644 (file)
index 0000000..3b9f38c
--- /dev/null
@@ -0,0 +1,201 @@
+\r
+#ifndef TUT_CPPUNIT_REPORTER\r
+#define TUT_CPPUNIT_REPORTER\r
+\r
+#include <tut/tut.hpp>\r
+#include <string>\r
+#include <fstream>\r
+#include <vector>\r
+#include <stdexcept>\r
+\r
+namespace tut\r
+{\r
+\r
+/**\r
+ * CppUnit TUT reporter\r
+ */\r
+class cppunit_reporter : public tut::callback\r
+{\r
+    private:\r
+        std::vector<tut::test_result> failed_tests;\r
+        std::vector<tut::test_result> passed_tests;\r
+        std::string filename;\r
+\r
+        std::string encode(const std::string & text)\r
+        {\r
+            std::string out;\r
+\r
+            for (unsigned int i=0; i<text.length(); ++i) {\r
+                char c = text[i];\r
+                switch (c) {\r
+                    case '<':\r
+                        out += "&lt;";\r
+                        break;\r
+                    case '>':\r
+                        out += "&gt;";\r
+                        break;\r
+                    case '&':\r
+                        out += "&amp;";\r
+                        break;\r
+                    case '\'':\r
+                        out += "&apos;";\r
+                        break;\r
+                    case '"':\r
+                        out += "&quot;";\r
+                        break;\r
+                    default:\r
+                        out += c;\r
+                }\r
+            }\r
+\r
+            return out;\r
+        }\r
+\r
+public:\r
+\r
+    cppunit_reporter(const std::string & _filename = "")\r
+    {\r
+        setFilename(_filename);\r
+    }\r
+\r
+    void setFilename(const std::string & _filename)\r
+    {\r
+        if (_filename == "")\r
+        {\r
+            filename = "testResult.xml";\r
+        }\r
+        else\r
+        {\r
+            filename = _filename;\r
+        }\r
+    }\r
+\r
+    void run_started()\r
+    {\r
+        failed_tests.clear();\r
+        passed_tests.clear();\r
+    }\r
+\r
+    void test_completed(const tut::test_result& tr)\r
+    {\r
+        if (tr.result == test_result::ok) {\r
+            passed_tests.push_back(tr);\r
+        } else {\r
+            failed_tests.push_back(tr);\r
+        }\r
+    }\r
+\r
+    void run_completed()\r
+    {\r
+        int errors = 0;\r
+        int failures = 0;\r
+        std::string failure_type;\r
+        std::string failure_msg;\r
+        std::ofstream xmlfile;\r
+\r
+        xmlfile.open(filename.c_str(), std::ios::in | std::ios::trunc);\r
+        if (!xmlfile.is_open()) {\r
+            throw (std::runtime_error("Cannot open file for output"));\r
+        }\r
+\r
+        /* *********************** header ***************************** */\r
+        xmlfile << "<?xml version=\"1.0\" encoding='ISO-8859-1' standalone='yes' ?>" << std::endl\r
+                << "<TestRun>" << std::endl;\r
+\r
+        /* *********************** failed tests ***************************** */\r
+        if (failed_tests.size() > 0) {\r
+            xmlfile << "  <FailedTests>" << std::endl;\r
+\r
+            for (unsigned int i=0; i<failed_tests.size(); i++) {\r
+                switch (failed_tests[i].result) {\r
+                    case test_result::fail:\r
+                        failure_type = "Assertion";\r
+                        failure_msg  = "";\r
+                        failures++;\r
+                        break;\r
+                    case test_result::ex:\r
+                        failure_type = "Assertion";\r
+                        failure_msg  = "Thrown exception: " + failed_tests[i].exception_typeid + '\n';\r
+                        failures++;\r
+                        break;\r
+                    case test_result::warn:\r
+                        failure_type = "Assertion";\r
+                        failure_msg  = "Destructor failed.\n";\r
+                        failures++;\r
+                        break;\r
+                    case test_result::term:\r
+                        failure_type = "Error";\r
+                        failure_msg  = "Test application terminated abnormally.\n";\r
+                        errors++;\r
+                        break;\r
+                    case test_result::ex_ctor:\r
+                        failure_type = "Error";\r
+                        failure_msg  = "Constructor has thrown an exception: " + failed_tests[i].exception_typeid + '\n';\r
+                        errors++;\r
+                        break;\r
+                    case test_result::rethrown:\r
+                        failure_type = "Assertion";\r
+                        failure_msg  = "Child failed";\r
+                        failures++;\r
+                        break;\r
+                    default:\r
+                        failure_type = "Error";\r
+                        failure_msg  = "Unknown test status, this should have never happened. "\r
+                                       "You may just have found a BUG in TUT CppUnit reporter, please report it immediately.\n";\r
+                        errors++;\r
+                        break;\r
+                }\r
+\r
+                xmlfile << "    <FailedTest id=\"" << failed_tests[i].test << "\">" << std::endl\r
+                        << "      <Name>" << encode(failed_tests[i].group) + "::" + encode(failed_tests[i].name) << "</Name>" << std::endl\r
+                        << "      <FailureType>" << failure_type << "</FailureType>" << std::endl\r
+                        << "      <Location>" << std::endl\r
+                        << "        <File>Unknown</File>" << std::endl\r
+                        << "        <Line>Unknown</Line>" << std::endl\r
+                        << "      </Location>" << std::endl\r
+                        << "      <Message>" << encode(failure_msg + failed_tests[i].message) << "</Message>" << std::endl\r
+                        << "    </FailedTest>" << std::endl;\r
+            }\r
+\r
+            xmlfile << "  </FailedTests>" << std::endl;\r
+        }\r
+\r
+        /* *********************** passed tests ***************************** */\r
+        if (passed_tests.size() > 0) {\r
+            xmlfile << "  <SuccessfulTests>" << std::endl;\r
+\r
+            for (unsigned int i=0; i<passed_tests.size(); i++) {\r
+                xmlfile << "    <Test id=\"" << passed_tests[i].test << "\">" << std::endl\r
+                        << "      <Name>" << encode(passed_tests[i].group) + "::" + encode(passed_tests[i].name) << "</Name>" << std::endl\r
+                        << "    </Test>" << std::endl;\r
+            }\r
+\r
+            xmlfile << "  </SuccessfulTests>" << std::endl;\r
+        }\r
+\r
+        /* *********************** statistics ***************************** */\r
+        xmlfile << "  <Statistics>" << std::endl\r
+                << "    <Tests>" << (failed_tests.size() + passed_tests.size()) << "</Tests>" << std::endl\r
+                << "    <FailuresTotal>" << failed_tests.size() << "</FailuresTotal>" << std::endl\r
+                << "    <Errors>" << errors << "</Errors>" << std::endl\r
+                << "    <Failures>" << failures << "</Failures>" << std::endl\r
+                << "  </Statistics>" << std::endl;\r
+\r
+        /* *********************** footer ***************************** */\r
+        xmlfile << "</TestRun>" << std::endl;\r
+\r
+        xmlfile.close();\r
+    }\r
+\r
+    bool all_ok() const\r
+    {\r
+        return failed_tests.empty();\r
+    };\r
+\r
+\r
+};\r
+\r
+}\r
+\r
+#endif\r
+\r