Unit Testing framework based on http://cpputest.github.io/

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers JUnitTestOutput.cpp Source File

JUnitTestOutput.cpp

00001 /*
00002  * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *     * Redistributions of source code must retain the above copyright
00008  *       notice, this list of conditions and the following disclaimer.
00009  *     * Redistributions in binary form must reproduce the above copyright
00010  *       notice, this list of conditions and the following disclaimer in the
00011  *       documentation and/or other materials provided with the distribution.
00012  *     * Neither the name of the <organization> nor the
00013  *       names of its contributors may be used to endorse or promote products
00014  *       derived from this software without specific prior written permission.
00015  *
00016  * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
00017  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00018  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00019  * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
00020  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00021  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00022  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00023  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00024  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00025  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026  */
00027 
00028 #include "CppUTest/TestHarness.h"
00029 #include "CppUTest/JUnitTestOutput.h"
00030 #include "CppUTest/TestResult.h"
00031 #include "CppUTest/TestFailure.h"
00032 #include "CppUTest/PlatformSpecificFunctions.h"
00033 
00034 struct JUnitTestCaseResultNode
00035 {
00036     JUnitTestCaseResultNode() :
00037         execTime_(0), failure_(0), next_(0)
00038     {
00039     }
00040 
00041     SimpleString name_;
00042     long execTime_;
00043     TestFailure* failure_;
00044     JUnitTestCaseResultNode* next_;
00045 };
00046 
00047 struct JUnitTestGroupResult
00048 {
00049     JUnitTestGroupResult() :
00050         testCount_(0), failureCount_(0), startTime_(0), groupExecTime_(0), head_(0), tail_(0)
00051     {
00052     }
00053 
00054     int testCount_;
00055     int failureCount_;
00056     long startTime_;
00057     long groupExecTime_;
00058     SimpleString group_;
00059     JUnitTestCaseResultNode* head_;
00060     JUnitTestCaseResultNode* tail_;
00061 };
00062 
00063 struct JUnitTestOutputImpl
00064 {
00065     JUnitTestGroupResult results_;
00066     PlatformSpecificFile file_;
00067     SimpleString package_;
00068 };
00069 
00070 JUnitTestOutput::JUnitTestOutput() :
00071     impl_(new JUnitTestOutputImpl)
00072 {
00073 }
00074 
00075 JUnitTestOutput::~JUnitTestOutput()
00076 {
00077     resetTestGroupResult();
00078     delete impl_;
00079 }
00080 
00081 void JUnitTestOutput::resetTestGroupResult()
00082 {
00083     impl_->results_.testCount_ = 0;
00084     impl_->results_.failureCount_ = 0;
00085     impl_->results_.group_ = "";
00086     JUnitTestCaseResultNode* cur = impl_->results_.head_;
00087     while (cur) {
00088         JUnitTestCaseResultNode* tmp = cur->next_;
00089         ;
00090         delete cur->failure_;
00091         delete cur;
00092         cur = tmp;
00093     }
00094     impl_->results_.head_ = 0;
00095     impl_->results_.tail_ = 0;
00096 }
00097 
00098 void JUnitTestOutput::printTestsStarted()
00099 {
00100 }
00101 
00102 void JUnitTestOutput::printCurrentGroupStarted(const UtestShell& /*test*/)
00103 {
00104 }
00105 
00106 void JUnitTestOutput::printCurrentTestEnded(const TestResult& result)
00107 {
00108     impl_->results_.tail_->execTime_
00109             = result.getCurrentTestTotalExecutionTime();
00110 }
00111 
00112 void JUnitTestOutput::printTestsEnded(const TestResult& /*result*/)
00113 {
00114 }
00115 
00116 void JUnitTestOutput::printCurrentGroupEnded(const TestResult& result)
00117 {
00118     impl_->results_.groupExecTime_ = result.getCurrentGroupTotalExecutionTime();
00119     writeTestGroupToFile();
00120     resetTestGroupResult();
00121 }
00122 
00123 void JUnitTestOutput::printCurrentTestStarted(const UtestShell& test)
00124 {
00125     impl_->results_.testCount_++;
00126     impl_->results_.group_ = test.getGroup();
00127     impl_->results_.startTime_ = GetPlatformSpecificTimeInMillis();
00128 
00129     if (impl_->results_.tail_ == 0) {
00130         impl_->results_.head_ = impl_->results_.tail_
00131                 = new JUnitTestCaseResultNode;
00132     }
00133     else {
00134         impl_->results_.tail_->next_ = new JUnitTestCaseResultNode;
00135         impl_->results_.tail_ = impl_->results_.tail_->next_;
00136     }
00137     impl_->results_.tail_->name_ = test.getName();
00138 }
00139 
00140 SimpleString JUnitTestOutput::createFileName(const SimpleString& group)
00141 {
00142     SimpleString fileName = "cpputest_";
00143     fileName += group;
00144     fileName.replace('/', '_');
00145     fileName += ".xml";
00146     return fileName;
00147 }
00148 
00149 void JUnitTestOutput::setPackageName(const SimpleString& package)
00150 {
00151     if (impl_ != NULL) {
00152         impl_->package_ = package;
00153     }
00154 }
00155 
00156 void JUnitTestOutput::writeXmlHeader()
00157 {
00158     writeToFile("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
00159 }
00160 
00161 void JUnitTestOutput::writeTestSuiteSummery()
00162 {
00163     SimpleString
00164             buf =
00165                     StringFromFormat(
00166                             "<testsuite errors=\"0\" failures=\"%d\" hostname=\"localhost\" name=\"%s\" tests=\"%d\" time=\"%d.%03d\" timestamp=\"%s\">\n",
00167                             impl_->results_.failureCount_,
00168                             impl_->results_.group_.asCharString(),
00169                             impl_->results_.testCount_,
00170                             (int) (impl_->results_.groupExecTime_ / 1000), (int) (impl_->results_.groupExecTime_ % 1000),
00171                             GetPlatformSpecificTimeString());
00172     writeToFile(buf.asCharString());
00173 }
00174 
00175 void JUnitTestOutput::writeProperties()
00176 {
00177     writeToFile("<properties>\n");
00178     writeToFile("</properties>\n");
00179 }
00180 
00181 void JUnitTestOutput::writeTestCases()
00182 {
00183     JUnitTestCaseResultNode* cur = impl_->results_.head_;
00184     while (cur) {
00185         SimpleString buf = StringFromFormat(
00186                 "<testcase classname=\"%s%s%s\" name=\"%s\" time=\"%d.%03d\">\n",
00187                 impl_->package_.asCharString(),
00188                 impl_->package_.isEmpty() == true ? "" : ".",
00189                 impl_->results_.group_.asCharString(),
00190                 cur->name_.asCharString(), (int) (cur->execTime_ / 1000), (int)(cur->execTime_ % 1000));
00191         writeToFile(buf.asCharString());
00192 
00193         if (cur->failure_) {
00194             writeFailure(cur);
00195         }
00196         writeToFile("</testcase>\n");
00197         cur = cur->next_;
00198     }
00199 }
00200 
00201 void JUnitTestOutput::writeFailure(JUnitTestCaseResultNode* node)
00202 {
00203     SimpleString message = node->failure_->getMessage().asCharString();
00204     message.replace('"', '\'');
00205     message.replace('<', '[');
00206     message.replace('>', ']');
00207     message.replace("&", "&amp;");
00208     message.replace("\n", "{newline}");
00209     SimpleString buf = StringFromFormat(
00210             "<failure message=\"%s:%d: %s\" type=\"AssertionFailedError\">\n",
00211             node->failure_->getFileName().asCharString(),
00212             node->failure_->getFailureLineNumber(), message.asCharString());
00213     writeToFile(buf.asCharString());
00214     writeToFile("</failure>\n");
00215 }
00216 
00217 void JUnitTestOutput::writeFileEnding()
00218 {
00219     writeToFile("<system-out></system-out>\n");
00220     writeToFile("<system-err></system-err>\n");
00221     writeToFile("</testsuite>");
00222 }
00223 
00224 void JUnitTestOutput::writeTestGroupToFile()
00225 {
00226     openFileForWrite(createFileName(impl_->results_.group_));
00227     writeXmlHeader();
00228     writeTestSuiteSummery();
00229     writeProperties();
00230     writeTestCases();
00231     writeFileEnding();
00232     closeFile();
00233 }
00234 
00235 void JUnitTestOutput::verbose()
00236 {
00237 }
00238 
00239 void JUnitTestOutput::printBuffer(const char*)
00240 {
00241 }
00242 
00243 void JUnitTestOutput::print(const char*)
00244 {
00245 }
00246 
00247 void JUnitTestOutput::print(long)
00248 {
00249 }
00250 
00251 void JUnitTestOutput::print(const TestFailure& failure)
00252 {
00253     if (impl_->results_.tail_->failure_ == 0) {
00254         impl_->results_.failureCount_++;
00255         impl_->results_.tail_->failure_ = new TestFailure(failure);
00256     }
00257 }
00258 
00259 void JUnitTestOutput::printTestRun(int /*number*/, int /*total*/)
00260 {
00261 }
00262 
00263 void JUnitTestOutput::flush()
00264 {
00265 }
00266 
00267 void JUnitTestOutput::openFileForWrite(const SimpleString& fileName)
00268 {
00269     impl_->file_ = PlatformSpecificFOpen(fileName.asCharString(), "w");
00270 }
00271 
00272 void JUnitTestOutput::writeToFile(const SimpleString& buffer)
00273 {
00274     PlatformSpecificFPuts(buffer.asCharString(), impl_->file_);
00275 }
00276 
00277 void JUnitTestOutput::closeFile()
00278 {
00279     PlatformSpecificFClose(impl_->file_);
00280 }