Commits

Matt Oswald  committed 2da5e8f

moved XmlReporter into utilities

  • Participants
  • Parent commits 4d13511

Comments (0)

Files changed (10)

File xUnit++.Utility/XmlReporter.cpp

+#include "XmlReporter.h"
+#include <chrono>
+#include <fstream>
+#include <iostream>
+#include "xUnit++/TestDetails.h"
+#include "xUnit++/TestEvent.h"
+#include "xUnit++/xUnitTime.h"
+
+namespace
+{
+    struct TestResult
+    {
+        TestResult()
+        {
+        }
+
+        TestResult(const xUnitpp::TestDetails &testDetails)
+            : testDetails(testDetails)
+            , status(Success)
+        {
+        }
+
+        xUnitpp::TestDetails testDetails;
+
+        enum
+        {
+            Success,
+            Failure,
+            Skipped
+        } status;
+
+        xUnitpp::Time::Duration time;
+        std::vector<std::string> messages;
+    };
+}
+
+struct xUnitpp::Utilities::XmlReporter::SuiteResult
+{
+    SuiteResult()
+    {
+    }
+
+    SuiteResult(const std::string &name)
+        : name(name)
+        , tests(0)
+        , failures(0)
+        , skipped(0)
+    {
+    }
+
+    std::string name;
+    int tests;
+    int failures;
+    int skipped;
+
+    std::map<std::string, TestResult> testResults;
+};
+
+namespace
+{
+    float SuiteTime(const xUnitpp::Utilities::XmlReporter::SuiteResult &suiteResult)
+    {
+        xUnitpp::Time::Duration timeTaken = xUnitpp::Time::Duration::zero();
+
+        for (const auto &test : suiteResult.testResults)
+        {
+            timeTaken += test.second.time;
+        }
+
+        return xUnitpp::Time::ToSeconds(timeTaken).count();
+    }
+
+    void ReplaceChar(std::string &str, char c, const std::string &replacement)
+    {
+        for (size_t pos = str.find(c); pos != std::string::npos; pos = str.find(c, pos + 1))
+        {
+            str.replace(pos, 1, replacement);
+        }
+    }
+
+    std::string XmlEscape(const std::string &value)
+    {
+        std::string escaped = value;
+
+        ReplaceChar(escaped, '&', "&amp;");
+        ReplaceChar(escaped, '<', "&lt;");
+        ReplaceChar(escaped, '>', "&gt;");
+        ReplaceChar(escaped, '\'', "&apos;");
+        ReplaceChar(escaped, '\"', "&quot;");
+
+        return escaped;
+    }
+
+    std::string XmlAttribute(const std::string &name, const std::string &value)
+    {
+        return " " + name + "=\"" + value + "\"";
+    }
+
+    std::string XmlAttribute(const std::string &name, const char *value)
+    {
+        return XmlAttribute(name, std::string(value));
+    }
+
+    template<typename T>
+    std::string XmlAttribute(const std::string &name, T value)
+    {
+        return XmlAttribute(name, std::to_string(value));
+    }
+
+    std::string XmlBeginDoc()
+    {
+        return
+            "<?xml" +
+                XmlAttribute("version", "1.0") +
+                XmlAttribute("encoding", "utf-8") +
+            " ?>\n";
+    }
+
+    std::string XmlBeginResults(size_t tests, size_t failures, xUnitpp::Time::Duration totalTime)
+    {
+        return
+            "<testsuites" +
+                XmlAttribute("tests", tests) +
+                XmlAttribute("failures", failures) +
+                XmlAttribute("time", xUnitpp::Time::ToSeconds(totalTime).count()) +
+            ">\n";
+    }
+
+    std::string XmlEndResults()
+    {
+        return "</testsuites>\n";
+    }
+
+    std::string XmlBeginSuite(const xUnitpp::Utilities::XmlReporter::SuiteResult &suite)
+    {
+        return std::string("   ") +
+            "<testsuite" +
+                XmlAttribute("name", suite.name) +
+                XmlAttribute("tests", suite.tests) +
+                XmlAttribute("failures", suite.failures) +
+                XmlAttribute("skipped", suite.skipped) +
+                XmlAttribute("time", SuiteTime(suite)) +
+            ">\n";
+    }
+
+    std::string XmlEndSuite()
+    {
+        return std::string("   ") +
+            "</testsuite>\n";
+    }
+
+    std::string XmlBeginTest(const std::string &testName, const TestResult &test)
+    {
+        return std::string("      ") +
+            "<testcase" +
+                XmlAttribute("name", testName) +
+                XmlAttribute("time", xUnitpp::Time::ToSeconds(test.time).count());
+    }
+
+    std::string XmlEndTest(bool singleTag)
+    {
+        if (singleTag)
+        {
+            return " />\n";
+        }
+
+        return std::string("      ") +
+            "</testcase>\n";
+    }
+
+    std::string XmlTestAttribute(const std::string &name, const std::string &value)
+    {
+        return std::string("         ") +
+            "<property" +
+                XmlAttribute("name", name) +
+                XmlAttribute("value", value) +
+            " />\n";
+    }
+
+    std::string XmlTestFailed(const std::string &fileAndLine, const std::vector<std::string> &messages)
+    {
+        std::string result;
+        for (const auto &message : messages)
+        {
+            result += std::string("         ") +
+                "<failure" +
+                    XmlAttribute("message", fileAndLine + ": " + XmlEscape(message)) +
+                "</failure>\n";
+        }
+
+        return result;
+    }
+
+    std::string XmlTestSkipped(const std::string &message)
+    {
+        return std::string("         ") +
+            "<skipped" +
+                XmlAttribute("message", XmlEscape(message)) +
+            "</skipped>\n";
+    }
+}
+
+namespace xUnitpp { namespace Utilities
+{
+
+XmlReporter::XmlReporter(const std::string &filename)
+    : filename(filename)
+{
+}
+
+void XmlReporter::ReportAllTestsComplete(size_t testCount, size_t, size_t failureCount, Time::Duration totalTime)
+{
+    auto report = [&](std::ostream &stream)
+        {
+            stream << XmlBeginDoc();
+            stream << XmlBeginResults(testCount, failureCount, totalTime);
+
+            for (const auto &itSuite : suiteResults)
+            {
+                stream << XmlBeginSuite(itSuite.second);
+
+                for (const auto &itTest : itSuite.second.testResults)
+                {
+                    const auto &test = itTest.second;
+
+                    stream << XmlBeginTest(itTest.first, test);
+
+                    if (test.status != TestResult::Success || !test.testDetails.Attributes.empty())
+                    {
+                        // close <TestCase>
+                        stream << ">\n";
+                    }
+
+                    for (const auto &att : test.testDetails.Attributes)
+                    {
+                        if (att.first != "Skip")
+                        {
+                            stream << XmlTestAttribute(att.first, att.second);
+                            break;
+                        }
+                    }
+
+                    if (test.status == TestResult::Failure)
+                    {
+                        stream << XmlTestFailed(to_string(test.testDetails.LineInfo), test.messages);
+                    }
+                    else if (test.status == TestResult::Skipped)
+                    {
+                        stream << XmlTestSkipped(test.messages[0]);
+                    }
+
+                    stream << XmlEndTest(test.status == TestResult::Success && test.testDetails.Attributes.empty());
+                }
+
+                stream << XmlEndSuite();
+            }
+
+            stream << XmlEndResults();
+
+        };
+
+    std::ofstream file(filename, std::ios::binary);
+
+    if (!file)
+    {
+        std::cerr << "Unable to open " << filename << " for writing.\n\n";
+
+        report(std::cerr);
+    }
+    else
+    {
+        report(file);
+    }
+}
+
+void XmlReporter::ReportStart(const TestDetails &testDetails)
+{
+    if (suiteResults.find(testDetails.Suite) == suiteResults.end())
+    {
+        suiteResults.insert(std::make_pair(testDetails.Suite, SuiteResult(testDetails.Suite)));
+    }
+
+    suiteResults[testDetails.Suite].tests++;
+    suiteResults[testDetails.Suite].testResults.insert(std::make_pair(testDetails.Name, TestResult(testDetails)));
+}
+
+void XmlReporter::ReportEvent(const TestDetails &testDetails, const TestEvent &evt)
+{
+    if (evt.IsFailure())
+    {
+        suiteResults[testDetails.Suite].failures++;
+        suiteResults[testDetails.Suite].testResults[testDetails.Name].messages.push_back(to_string(evt));
+        suiteResults[testDetails.Suite].testResults[testDetails.Name].status = TestResult::Failure;
+    }
+}
+
+void XmlReporter::ReportSkip(const TestDetails &testDetails, const std::string &reason)
+{
+    ReportStart(testDetails);
+    suiteResults[testDetails.Suite].skipped++;
+    suiteResults[testDetails.Suite].testResults[testDetails.Name].messages.push_back(reason);
+    suiteResults[testDetails.Suite].testResults[testDetails.Name].status = TestResult::Skipped;
+}
+
+void XmlReporter::ReportFinish(const TestDetails &testDetails, Time::Duration timeTaken)
+{
+    suiteResults[testDetails.Suite].testResults[testDetails.Name].time = timeTaken;
+}
+
+}}

File xUnit++.Utility/XmlReporter.h

+#ifndef XMLREPORTER_H_
+#define XMLREPORTER_H_
+
+#include <map>
+#include "xUnit++/IOutput.h"
+
+namespace xUnitpp { namespace Utilities
+{
+
+class XmlReporter : public IOutput
+{
+public:
+    XmlReporter(const std::string &filename);
+
+    virtual void ReportStart(const TestDetails &td) override;
+    virtual void ReportEvent(const TestDetails &testDetails, const TestEvent &evt) override;
+    virtual void ReportSkip(const TestDetails &testDetails, const std::string &reason) override;
+    virtual void ReportFinish(const TestDetails &testDetails, Time::Duration timeTaken) override;
+    virtual void ReportAllTestsComplete(size_t testCount, size_t skipped, size_t failureCount, Time::Duration totalTime) override;
+
+public:
+    struct SuiteResult;
+
+private:
+    std::string filename;
+    std::map<std::string, SuiteResult> suiteResults;
+};
+
+}}
+
+#endif

File xUnit++.Utility/xUnit++.Utility.vcxproj

   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="TestAssembly.cpp" />
+    <ClCompile Include="XmlReporter.cpp" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="TestAssembly.h" />
+    <ClInclude Include="XmlReporter.h" />
   </ItemGroup>
   <PropertyGroup Label="Globals">
     <VCTargetsPath Condition="'$(VCTargetsPath11)' != '' and '$(VSVersion)' == '' and '$(VisualStudioVersion)' == ''">$(VCTargetsPath11)</VCTargetsPath>

File xUnit++.Utility/xUnit++.Utility.vcxproj.filters

 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup>
     <ClCompile Include="TestAssembly.cpp" />
+    <ClCompile Include="XmlReporter.cpp" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="TestAssembly.h" />
+    <ClInclude Include="XmlReporter.h" />
   </ItemGroup>
 </Project>

File xUnit++.console/ConsoleReporter.cpp

 
 void ConsoleReporter::ReportSkip(const TestDetails &testDetails, const std::string &reason)
 {
-    CachedOutput::Instant(FileAndLine(testDetails, LineInfo::empty()) +
+    CachedOutput::Instant(to_string(testDetails.LineInfo) +
         ": skipping " + testDetails.Name + ": " + reason);
 }
 

File xUnit++.console/XmlReporter.cpp

-#include "XmlReporter.h"
-#include <chrono>
-#include <fstream>
-#include <iostream>
-#include "xUnit++/TestDetails.h"
-#include "xUnit++/TestEvent.h"
-#include "xUnit++/xUnitTime.h"
-
-namespace
-{
-    struct TestResult
-    {
-        TestResult()
-        {
-        }
-
-        TestResult(const xUnitpp::TestDetails &testDetails)
-            : testDetails(testDetails)
-            , status(Success)
-        {
-        }
-
-        xUnitpp::TestDetails testDetails;
-
-        enum
-        {
-            Success,
-            Failure,
-            Skipped
-        } status;
-
-        xUnitpp::Time::Duration time;
-        std::vector<std::string> messages;
-    };
-}
-
-struct xUnitpp::XmlReporter::SuiteResult
-{
-    SuiteResult()
-    {
-    }
-
-    SuiteResult(const std::string &name)
-        : name(name)
-        , tests(0)
-        , failures(0)
-        , skipped(0)
-    {
-    }
-
-    std::string name;
-    int tests;
-    int failures;
-    int skipped;
-
-    std::map<std::string, TestResult> testResults;
-};
-
-namespace
-{
-    float SuiteTime(const xUnitpp::XmlReporter::SuiteResult &suiteResult)
-    {
-        xUnitpp::Time::Duration timeTaken = xUnitpp::Time::Duration::zero();
-
-        for (const auto &test : suiteResult.testResults)
-        {
-            timeTaken += test.second.time;
-        }
-
-        return xUnitpp::Time::ToSeconds(timeTaken).count();
-    }
-
-    void ReplaceChar(std::string &str, char c, const std::string &replacement)
-    {
-        for (size_t pos = str.find(c); pos != std::string::npos; pos = str.find(c, pos + 1))
-        {
-            str.replace(pos, 1, replacement);
-        }
-    }
-
-    std::string XmlEscape(const std::string &value)
-    {
-        std::string escaped = value;
-
-        ReplaceChar(escaped, '&', "&amp;");
-        ReplaceChar(escaped, '<', "&lt;");
-        ReplaceChar(escaped, '>', "&gt;");
-        ReplaceChar(escaped, '\'', "&apos;");
-        ReplaceChar(escaped, '\"', "&quot;");
-
-        return escaped;
-    }
-
-    std::string XmlAttribute(const std::string &name, const std::string &value)
-    {
-        return " " + name + "=\"" + value + "\"";
-    }
-
-    std::string XmlAttribute(const std::string &name, const char *value)
-    {
-        return XmlAttribute(name, std::string(value));
-    }
-
-    template<typename T>
-    std::string XmlAttribute(const std::string &name, T value)
-    {
-        return XmlAttribute(name, std::to_string(value));
-    }
-
-    std::string XmlBeginDoc()
-    {
-        return
-            "<?xml" +
-                XmlAttribute("version", "1.0") +
-                XmlAttribute("encoding", "utf-8") +
-            " ?>\n";
-    }
-
-    std::string XmlBeginResults(size_t tests, size_t failures, xUnitpp::Time::Duration totalTime)
-    {
-        return
-            "<testsuites" +
-                XmlAttribute("tests", tests) +
-                XmlAttribute("failures", failures) +
-                XmlAttribute("time", xUnitpp::Time::ToSeconds(totalTime).count()) +
-            ">\n";
-    }
-
-    std::string XmlEndResults()
-    {
-        return "</testsuites>\n";
-    }
-
-    std::string XmlBeginSuite(const xUnitpp::XmlReporter::SuiteResult &suite)
-    {
-        return std::string("   ") +
-            "<testsuite" +
-                XmlAttribute("name", suite.name) +
-                XmlAttribute("tests", suite.tests) +
-                XmlAttribute("failures", suite.failures) +
-                XmlAttribute("skipped", suite.skipped) +
-                XmlAttribute("time", SuiteTime(suite)) +
-            ">\n";
-    }
-
-    std::string XmlEndSuite()
-    {
-        return std::string("   ") +
-            "</testsuite>\n";
-    }
-
-    std::string XmlBeginTest(const std::string &testName, const TestResult &test)
-    {
-        return std::string("      ") +
-            "<testcase" +
-                XmlAttribute("name", testName) +
-                XmlAttribute("time", xUnitpp::Time::ToSeconds(test.time).count());
-    }
-
-    std::string XmlEndTest(bool singleTag)
-    {
-        if (singleTag)
-        {
-            return " />\n";
-        }
-
-        return std::string("      ") +
-            "</testcase>\n";
-    }
-
-    std::string XmlTestAttribute(const std::string &name, const std::string &value)
-    {
-        return std::string("         ") +
-            "<property" +
-                XmlAttribute("name", name) +
-                XmlAttribute("value", value) +
-            " />\n";
-    }
-
-    std::string XmlTestFailed(const std::string &fileAndLine, const std::vector<std::string> &messages)
-    {
-        std::string result;
-        for (const auto &message : messages)
-        {
-            result += std::string("         ") +
-                "<failure" +
-                    XmlAttribute("message", fileAndLine + ": " + XmlEscape(message)) +
-                "</failure>\n";
-        }
-
-        return result;
-    }
-
-    std::string XmlTestSkipped(const std::string &message)
-    {
-        return std::string("         ") +
-            "<skipped" +
-                XmlAttribute("message", XmlEscape(message)) +
-            "</skipped>\n";
-    }
-}
-
-namespace xUnitpp
-{
-
-XmlReporter::XmlReporter(const std::string &filename)
-    : filename(filename)
-{
-}
-
-void XmlReporter::ReportAllTestsComplete(size_t testCount, size_t, size_t failureCount, Time::Duration totalTime)
-{
-    auto report = [&](std::ostream &stream)
-        {
-            stream << XmlBeginDoc();
-            stream << XmlBeginResults(testCount, failureCount, totalTime);
-
-            for (const auto &itSuite : suiteResults)
-            {
-                stream << XmlBeginSuite(itSuite.second);
-
-                for (const auto &itTest : itSuite.second.testResults)
-                {
-                    const auto &test = itTest.second;
-
-                    stream << XmlBeginTest(itTest.first, test);
-
-                    if (test.status != TestResult::Success || !test.testDetails.Attributes.empty())
-                    {
-                        // close <TestCase>
-                        stream << ">\n";
-                    }
-
-                    for (const auto &att : test.testDetails.Attributes)
-                    {
-                        if (att.first != "Skip")
-                        {
-                            stream << XmlTestAttribute(att.first, att.second);
-                            break;
-                        }
-                    }
-
-                    if (test.status == TestResult::Failure)
-                    {
-                        stream << XmlTestFailed(to_string(test.testDetails.LineInfo), test.messages);
-                    }
-                    else if (test.status == TestResult::Skipped)
-                    {
-                        stream << XmlTestSkipped(test.messages[0]);
-                    }
-
-                    stream << XmlEndTest(test.status == TestResult::Success && test.testDetails.Attributes.empty());
-                }
-
-                stream << XmlEndSuite();
-            }
-
-            stream << XmlEndResults();
-
-        };
-
-    std::ofstream file(filename, std::ios::binary);
-
-    if (!file)
-    {
-        std::cerr << "Unable to open " << filename << " for writing.\n\n";
-
-        report(std::cerr);
-    }
-    else
-    {
-        report(file);
-    }
-}
-
-void XmlReporter::ReportStart(const TestDetails &testDetails)
-{
-    if (suiteResults.find(testDetails.Suite) == suiteResults.end())
-    {
-        suiteResults.insert(std::make_pair(testDetails.Suite, SuiteResult(testDetails.Suite)));
-    }
-
-    suiteResults[testDetails.Suite].tests++;
-    suiteResults[testDetails.Suite].testResults.insert(std::make_pair(testDetails.Name, TestResult(testDetails)));
-}
-
-void XmlReporter::ReportEvent(const TestDetails &testDetails, const TestEvent &evt)
-{
-    if (evt.IsFailure())
-    {
-        suiteResults[testDetails.Suite].failures++;
-        suiteResults[testDetails.Suite].testResults[testDetails.Name].messages.push_back(to_string(evt));
-        suiteResults[testDetails.Suite].testResults[testDetails.Name].status = TestResult::Failure;
-    }
-}
-
-void XmlReporter::ReportSkip(const TestDetails &testDetails, const std::string &reason)
-{
-    ReportStart(testDetails);
-    suiteResults[testDetails.Suite].skipped++;
-    suiteResults[testDetails.Suite].testResults[testDetails.Name].messages.push_back(reason);
-    suiteResults[testDetails.Suite].testResults[testDetails.Name].status = TestResult::Skipped;
-}
-
-void XmlReporter::ReportFinish(const TestDetails &testDetails, Time::Duration timeTaken)
-{
-    suiteResults[testDetails.Suite].testResults[testDetails.Name].time = timeTaken;
-}
-
-}

File xUnit++.console/XmlReporter.h

-#ifndef XMLREPORTER_H_
-#define XMLREPORTER_H_
-
-#include <map>
-#include "xUnit++/IOutput.h"
-
-namespace xUnitpp
-{
-
-class XmlReporter : public IOutput
-{
-public:
-    XmlReporter(const std::string &filename);
-
-    virtual void ReportStart(const TestDetails &td) override;
-    virtual void ReportEvent(const TestDetails &testDetails, const TestEvent &evt) override;
-    virtual void ReportSkip(const TestDetails &testDetails, const std::string &reason) override;
-    virtual void ReportFinish(const TestDetails &testDetails, Time::Duration timeTaken) override;
-    virtual void ReportAllTestsComplete(size_t testCount, size_t skipped, size_t failureCount, Time::Duration totalTime) override;
-
-public:
-    struct SuiteResult;
-
-private:
-    std::string filename;
-    std::map<std::string, SuiteResult> suiteResults;
-};
-
-}
-
-#endif

File xUnit++.console/main.cpp

 
             std::unique_ptr<xUnitpp::IOutput> reporter(options.xmlOutput.empty() ?
                 (xUnitpp::IOutput *)new xUnitpp::ConsoleReporter(options.verbose, options.veryVerbose) :
-                (xUnitpp::IOutput *)new xUnitpp::XmlReporter(options.xmlOutput));
+                (xUnitpp::IOutput *)new xUnitpp::Utilities::XmlReporter(options.xmlOutput));
             totalFailures += testAssembly.FilteredTestsRunner(options.timeLimit, options.threadLimit, *reporter,
                 [&](const xUnitpp::TestDetails &testDetails)
                 {

File xUnit++.console/xUnit++.console.vcxproj

     <ClCompile Include="CommandLine.cpp" />
     <ClCompile Include="ConsoleReporter.cpp" />
     <ClCompile Include="main.cpp" />
-    <ClCompile Include="XmlReporter.cpp" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\xUnit++.Utility\xUnit++.Utility.vcxproj">
   <ItemGroup>
     <ClInclude Include="CommandLine.h" />
     <ClInclude Include="ConsoleReporter.h" />
-    <ClInclude Include="XmlReporter.h" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">

File xUnit++.console/xUnit++.console.vcxproj.filters

   <ItemGroup>
     <ClCompile Include="main.cpp" />
     <ClCompile Include="CommandLine.cpp" />
-    <ClCompile Include="XmlReporter.cpp" />
     <ClCompile Include="ConsoleReporter.cpp" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="CommandLine.h" />
-    <ClInclude Include="XmlReporter.h" />
     <ClInclude Include="ConsoleReporter.h" />
   </ItemGroup>
 </Project>