Vault  4.1
vunit.cpp
Go to the documentation of this file.
00001 /*
00002 Copyright c1997-2014 Trygve Isaacson. All rights reserved.
00003 This file is part of the Code Vault version 4.1
00004 http://www.bombaydigital.com/
00005 License: MIT. See LICENSE.md in the Vault top level directory.
00006 */
00007 
00010 #include "vunit.h"
00011 
00012 #include "vlogger.h"
00013 #include "vexception.h"
00014 #include "vtextiostream.h"
00015 
00016 // VUnit ---------------------------------------------------------------------
00017 
00018 // static
00019 void VUnit::runUnit(VUnit& unit, VUnitOutputWriterList* writers) {
00020     unit.setWriters(writers);
00021 
00022     unit.logStart();
00023 
00024     try {
00025         VAutoreleasePool pool;
00026         unit.run();
00027     } catch (const std::exception& ex) { // will include VException
00028         unit.logExceptionalEnd(ex.what());
00029         throw;
00030     } catch (...) {
00031         unit.logExceptionalEnd("(exception type unknown)");
00032         throw;
00033     }
00034 
00035     unit.logNormalEnd();
00036 }
00037 
00038 void VUnit::rerunUnit(VUnit& unit, VUnitOutputWriterList* writers) {
00039     unit.reset();
00040     VUnit::runUnit(unit, writers);
00041 }
00042 
00043 VUnit::VUnit(const VString& name, bool logOnSuccess, bool throwOnError) :
00044     mName(name),
00045     mLogOnSuccess(logOnSuccess),
00046     mThrowOnError(throwOnError),
00047     mWriters(NULL),
00048     mNumSuccessfulTests(0),
00049     mNumFailedTests(0),
00050     mResults(),
00051     mUnitStartTimeSnapshot(VInstant::snapshot()),
00052     mPreviousTestEndedSnapshot(VInstant::snapshot()),
00053     mLastTestDescription() {
00054 }
00055 
00056 VUnit::~VUnit() {
00057 }
00058 
00059 void VUnit::reset() {
00060     mNumSuccessfulTests = 0;
00061     mNumFailedTests = 0;
00062     mResults.clear();
00063     mUnitStartTimeSnapshot = VInstant::snapshot();
00064     mPreviousTestEndedSnapshot = VInstant::snapshot();
00065     mLastTestDescription = VString::EMPTY();
00066 }
00067 
00068 void VUnit::logStart() {
00069     if (mWriters != NULL)
00070         for (VUnitOutputWriterList::iterator i = mWriters->begin(); i != mWriters->end(); ++i)
00071             (*i)->testSuiteBegin(mName);
00072 }
00073 
00074 void VUnit::logNormalEnd() {
00075     if (mWriters != NULL)
00076         for (VUnitOutputWriterList::iterator i = mWriters->begin(); i != mWriters->end(); ++i)
00077             (*i)->testSuiteEnd();
00078 }
00079 
00080 void VUnit::logExceptionalEnd(const VString& exceptionMessage) {
00081     VTestInfo error(false, VSTRING_FORMAT("after %s, threw exception: %s", mLastTestDescription.chars(), exceptionMessage.chars()), VDuration::ZERO());
00082     mResults.push_back(error);
00083 
00084     ++mNumFailedTests;
00085 
00086     if (mWriters != NULL)
00087         for (VUnitOutputWriterList::iterator i = mWriters->begin(); i != mWriters->end(); ++i) {
00088             (*i)->testCaseBegin("exception thrown");
00089             (*i)->testCaseEnd(error);
00090         }
00091 }
00092 
00093 void VUnit::assertSuccess(const VString& labelSuffix, const VString& filePath, int lineNumber) {
00094     VString fileName;
00095     filePath.getSubstring(fileName, filePath.lastIndexOf('/') + 1);
00096     VString testName(VSTRING_ARGS("%s:%d %s", fileName.chars(), lineNumber, labelSuffix.chars()));
00097 
00098     mLastTestDescription = testName;
00099 
00100     this->recordSuccess(testName);
00101 
00102     mPreviousTestEndedSnapshot = VInstant::snapshot();
00103 }
00104 
00105 void VUnit::assertFailure(const VString& labelSuffix, const VString& filePath, int lineNumber) {
00106     VString fileName;
00107     filePath.getSubstring(fileName, filePath.lastIndexOf('/') + 1);
00108     VString testName(VSTRING_ARGS("%s:%d %s", fileName.chars(), lineNumber, labelSuffix.chars()));
00109 
00110     mLastTestDescription = testName;
00111 
00112     this->recordFailure(VSTRING_FORMAT("%s: %s", testName.chars()));
00113 
00114     mPreviousTestEndedSnapshot = VInstant::snapshot();
00115 }
00116 
00117 void VUnit::testAssertion(bool successful, const VString& filePath, int lineNumber, const VString& labelSuffix, const VString& expectedDescription) {
00118     VString fileName;
00119     filePath.getSubstring(fileName, filePath.lastIndexOf('/') + 1);
00120     VString testName(VSTRING_ARGS("%s:%d %s", fileName.chars(), lineNumber, labelSuffix.chars()));
00121 
00122     mLastTestDescription = testName;
00123 
00124     if (successful)
00125         this->recordSuccess(testName);
00126     else
00127         this->recordFailure(VSTRING_FORMAT("%s: %s", testName.chars(), expectedDescription.chars()));
00128 
00129     mPreviousTestEndedSnapshot = VInstant::snapshot();
00130 }
00131 
00132 void VUnit::test(bool successful, const VString& description) {
00133     mLastTestDescription = description;
00134 
00135     if (successful)
00136         this->recordSuccess(description);
00137     else
00138         this->recordFailure(description);
00139 
00140     mPreviousTestEndedSnapshot = VInstant::snapshot();
00141 }
00142 
00143 void VUnit::test(const VString& a, const VString& b, const VString& description) {
00144     this->test(a == b, description);
00145 }
00146 
00147 void VUnit::logStatus(const VString& description) {
00148     if (mWriters != NULL)
00149         for (VUnitOutputWriterList::iterator i = mWriters->begin(); i != mWriters->end(); ++i)
00150             (*i)->testSuiteStatusMessage(description);
00151 }
00152 
00153 void VUnit::recordSuccess(const VString& description) {
00154     if (mWriters != NULL)
00155         for (VUnitOutputWriterList::iterator i = mWriters->begin(); i != mWriters->end(); ++i)
00156             (*i)->testCaseBegin(description);
00157 
00158     ++mNumSuccessfulTests;
00159 
00160     VTestInfo info(true, description, VInstant::snapshotDelta(mPreviousTestEndedSnapshot));
00161     mResults.push_back(info);
00162 
00163     if (mWriters != NULL)
00164         for (VUnitOutputWriterList::iterator i = mWriters->begin(); i != mWriters->end(); ++i)
00165             (*i)->testCaseEnd(info);
00166 }
00167 
00168 void VUnit::recordFailure(const VString& description) {
00169     if (mWriters != NULL)
00170         for (VUnitOutputWriterList::iterator i = mWriters->begin(); i != mWriters->end(); ++i)
00171             (*i)->testCaseBegin(description);
00172 
00173     ++mNumFailedTests;
00174 
00175     VTestInfo info(false, description, VInstant::snapshotDelta(mPreviousTestEndedSnapshot));
00176     mResults.push_back(info);
00177 
00178     if (mWriters != NULL)
00179         for (VUnitOutputWriterList::iterator i = mWriters->begin(); i != mWriters->end(); ++i)
00180             (*i)->testCaseEnd(info);
00181 }
00182 
00183 // VTestInfo -----------------------------------------------------------------
00184 
00185 VTestInfo::VTestInfo(bool success, const VString& description, const VDuration& duration) :
00186     mSuccess(success),
00187     mDescription(description),
00188     mDuration(duration) {
00189     // Some tests that manipulate time simulation will yield bogus durations.
00190     if ((mDuration < VDuration::ZERO()) || (mDuration > VDuration::DAY()))
00191         mDuration = VDuration::ZERO();
00192 }
00193 
00194 // VFailureEmitter -----------------------------------------------------------
00195 
00196 VFailureEmitter::VFailureEmitter(const VString& testName, bool logOnSuccess, bool throwOnError, const VString& errorMessage) :
00197     VUnit(testName, logOnSuccess, throwOnError), fErrorMessage(errorMessage) {
00198 }
00199 
00200 void VFailureEmitter::run() {
00201     this->logStatus(VSTRING_FORMAT("%s failed due to this error: %s", this->getName().chars(), fErrorMessage.chars()));
00202     this->test(false, fErrorMessage);
00203 }
00204 
00205 // VUnitOutputWriter ------------------------------------------------------
00206 
00207 static const VString VUNIT_OUTPUT_DIRECTIVE("-vunit-out");
00208 
00209 static const VString OUTPUT_TYPE_SIMPLE("text");
00210 static const VString OUTPUT_TYPE_JUNIT("junit");
00211 static const VString OUTPUT_TYPE_TEAMCITY("tc");
00212 static const VString OUTPUT_TYPE_TEAMCITY_STATUS("tcstatus");
00213 
00214 static const VString OUTPUT_FILEPATH_STDOUT("stdout");
00215 
00216 // static
00217 void VUnitOutputWriter::createOutputWriters(const VStringVector& args, VUnitOutputWriterList& writers, VUnitLogAppenderList& appenders) {
00218     for (VStringVector::const_iterator i = args.begin(); i != args.end(); ++i) {
00219         if ((*i) == VUNIT_OUTPUT_DIRECTIVE) {
00220             VString outputType = *(++i);
00221             VString filePath = *(++i);
00222             VUnitOutputWriter::_addNewOutputWriter(writers, appenders, outputType, filePath);
00223         }
00224     }
00225 
00226     // If no specific output was specified, log simple output to stdout.
00227     if (writers.size() == 0)
00228         VUnitOutputWriter::_addNewOutputWriter(writers, appenders, OUTPUT_TYPE_SIMPLE, OUTPUT_FILEPATH_STDOUT);
00229 }
00230 
00231 VUnitOutputWriter::VUnitOutputWriter(VLogAppender& outputAppender) :
00232     mLogAppender(outputAppender),
00233     mTestSuitesStartTime(VInstant::NEVER_OCCURRED()),
00234     mTotalNumSuccesses(0),
00235     mTotalNumErrors(0),
00236     mCurrentTestSuiteName(),
00237     mCurrentTestSuiteResults(),
00238     mCurrentTestSuiteNumSuccesses(0),
00239     mCurrentTestSuiteNumErrors(0),
00240     mCurrentTestSuiteStartTime(VInstant::NEVER_OCCURRED()),
00241     mCurrentTestSuiteEndTime(VInstant::NEVER_OCCURRED()),
00242     mCurrentTestCaseName(),
00243     mCurrentTestCaseStartTime(VInstant::NEVER_OCCURRED()),
00244     mCurrentTestCaseEndTime(VInstant::NEVER_OCCURRED()),
00245     mFailedTestSuiteNames() {
00246 }
00247 
00248 void VUnitOutputWriter::_testSuitesBegin() {
00249     mTestSuitesStartTime.setNow();
00250 }
00251 
00252 void VUnitOutputWriter::_testSuiteBegin(const VString& testSuiteName) {
00253     mCurrentTestSuiteName = testSuiteName;
00254     mCurrentTestSuiteResults.clear();
00255     mCurrentTestSuiteNumSuccesses = 0;
00256     mCurrentTestSuiteNumErrors = 0;
00257     mCurrentTestSuiteStartTime.setNow();
00258     mCurrentTestSuiteEndTime = VInstant::NEVER_OCCURRED();
00259     mCurrentTestCaseStartTime = VInstant::NEVER_OCCURRED();
00260     mCurrentTestCaseEndTime = VInstant::NEVER_OCCURRED();
00261 }
00262 
00263 void VUnitOutputWriter::_testCaseBegin(const VString& testCaseName) {
00264     mCurrentTestCaseName = testCaseName;
00265     mCurrentTestCaseStartTime.setNow();
00266 }
00267 
00268 void VUnitOutputWriter::_testCaseEnd(const VTestInfo& testInfo) {
00269     mCurrentTestCaseEndTime.setNow();
00270     mCurrentTestSuiteResults.push_back(testInfo);
00271 
00272     if (testInfo.mSuccess) {
00273         ++mTotalNumSuccesses;
00274         ++mCurrentTestSuiteNumSuccesses;
00275     } else {
00276         ++mTotalNumErrors;
00277         ++mCurrentTestSuiteNumErrors;
00278     }
00279 }
00280 
00281 void VUnitOutputWriter::_testSuiteEnd() {
00282     mCurrentTestSuiteEndTime.setNow();
00283 
00284     if (mCurrentTestSuiteNumErrors != 0)
00285         mFailedTestSuiteNames.push_back(mCurrentTestSuiteName);
00286 }
00287 
00288 // static
00289 VLogAppender* VUnitOutputWriter::_newLogAppenderByType(const VString& outputType, const VString& filePath) {
00290     // We allow either cout logging, or file logging.
00291     VLogAppender* appender = NULL;
00292     if (filePath == OUTPUT_FILEPATH_STDOUT) {
00293         appender = new VCoutLogAppender(VSTRING_FORMAT("vunit-%s-cout", outputType.chars()), false, VString::EMPTY(), VString::EMPTY());
00294     } else {
00295         VFSNode logFile(filePath);
00296         logFile.rm();
00297         appender = new VFileLogAppender(VSTRING_FORMAT("vunit-%s-%s", outputType.chars(), filePath.chars()), false, VString::EMPTY(), VString::EMPTY(), filePath);
00298     }
00299 
00300     return appender;
00301 }
00302 
00303 // static
00304 VUnitOutputWriter* VUnitOutputWriter::_newOutputWriterByType(const VString& outputType, VLogAppender* appender) {
00305     VUnitOutputWriter* writer = NULL;
00306 
00307     if (outputType == OUTPUT_TYPE_SIMPLE) {
00308         writer = new VUnitSimpleTextOutput(*appender);
00309     } else if (outputType == OUTPUT_TYPE_JUNIT) {
00310         writer = new VUnitJUnitXMLOutput(*appender);
00311     } else if (outputType == OUTPUT_TYPE_TEAMCITY) {
00312         writer = new VUnitTeamCityOutput(*appender);
00313     } else if (outputType == OUTPUT_TYPE_TEAMCITY_STATUS) {
00314         writer = new VUnitTeamCityBuildStatusOutput(*appender);
00315     } else {
00316         VLOGGER_ERROR(VSTRING_FORMAT("Invalid unit test output type '%s' will be ignored.", outputType.chars()));
00317     }
00318 
00319     return writer;
00320 }
00321 
00322 // static
00323 void VUnitOutputWriter::_addNewOutputWriter(VUnitOutputWriterList& outputters, VUnitLogAppenderList& outputAppenders, const VString& outputType, const VString& filePath) {
00324     VLogAppender* appender = VUnitOutputWriter::_newLogAppenderByType(outputType, filePath);
00325     VUnitOutputWriter* outputInterface = VUnitOutputWriter::_newOutputWriterByType(outputType, appender);
00326 
00327     if (outputInterface == NULL) {
00328         delete appender;
00329     } else {
00330         outputAppenders.push_back(appender);
00331         outputters.push_back(outputInterface);
00332     }
00333 }
00334 
00335 // VTestSuitesWrapper --------------------------------------------------------
00336 
00337 VTestSuitesWrapper::VTestSuitesWrapper(const VStringVector& args) :
00338     mWriters(),
00339     mAppenders() {
00340     VUnitOutputWriter::createOutputWriters(args, mWriters, mAppenders);
00341 
00342     for (VUnitOutputWriterList::iterator i = mWriters.begin(); i != mWriters.end(); ++i)
00343         (*i)->testSuitesBegin();
00344 }
00345 
00346 VTestSuitesWrapper::~VTestSuitesWrapper() {
00347     for (VUnitOutputWriterList::iterator i = mWriters.begin(); i != mWriters.end(); ++i)
00348         (*i)->testSuitesEnd();
00349 
00350     vault::vectorDeleteAll(mWriters);
00351     vault::vectorDeleteAll(mAppenders);
00352 }
00353 
00354 // VUnitJUnitXMLOutput -------------------------------------------------------
00355 
00356 static VString _escapeXMLString(const VString& original) {
00357     VString result(original);
00358 
00359     result.replace("&", "&amp;");
00360     result.replace("\"", "&quot;");
00361     result.replace("<", "&lt;");
00362     result.replace(">", "&gt;");
00363 
00364     return result;
00365 }
00366 
00367 VUnitJUnitXMLOutput::VUnitJUnitXMLOutput(VLogAppender& outputAppender) :
00368     VUnitOutputWriter(outputAppender) {
00369 }
00370 
00371 void VUnitJUnitXMLOutput::testSuitesBegin() {
00372     this->_testSuitesBegin();
00373 
00374     mLogAppender.emitRaw("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
00375     mLogAppender.emitRaw("<testsuites>");
00376 }
00377 
00378 void VUnitJUnitXMLOutput::testSuiteBegin(const VString& testSuiteName) {
00379     this->_testSuiteBegin(testSuiteName);
00380 }
00381 
00382 void VUnitJUnitXMLOutput::testSuiteStatusMessage(const VString& /*message*/) {
00383 }
00384 
00385 void VUnitJUnitXMLOutput::testCaseBegin(const VString& testCaseName) {
00386     this->_testCaseBegin(testCaseName);
00387 }
00388 
00389 void VUnitJUnitXMLOutput::testCaseEnd(const VTestInfo& testInfo) {
00390     this->_testCaseEnd(testInfo);
00391 }
00392 
00393 void VUnitJUnitXMLOutput::testSuiteEnd() {
00394     this->_testSuiteEnd();
00395 
00396     VDuration testSuiteDuration = mCurrentTestSuiteEndTime - mCurrentTestSuiteStartTime;
00397 
00398     mLogAppender.emitRaw(VSTRING_FORMAT(" <testsuite errors=\"%d\" failures=\"0\" name=\"%s\" tests=\"%d\" time=\"%s\">",
00399                                         mCurrentTestSuiteNumErrors, mCurrentTestSuiteName.chars(), (int)mCurrentTestSuiteResults.size(), testSuiteDuration.getDurationString().chars()));
00400 
00401     for (TestInfoVector::const_iterator i = mCurrentTestSuiteResults.begin(); i != mCurrentTestSuiteResults.end(); ++i) {
00402         mLogAppender.emitRaw(VSTRING_FORMAT("  <testcase class=\"%s\" name=\"%s\" time=\"%s\"></testcase>",
00403                                             mCurrentTestSuiteName.chars(), _escapeXMLString((*i).mDescription).chars(), (*i).mDuration.getDurationString().chars()));
00404     }
00405 
00406     mLogAppender.emitRaw(" </testsuite>");
00407 }
00408 
00409 void VUnitJUnitXMLOutput::testSuitesEnd() {
00410     mLogAppender.emitRaw("</testsuites>");
00411 }
00412 
00413 // VUnitSimpleTextOutput -----------------------------------------------------
00414 
00415 VUnitSimpleTextOutput::VUnitSimpleTextOutput(VLogAppender& outputAppender) :
00416     VUnitOutputWriter(outputAppender) {
00417 }
00418 
00419 void VUnitSimpleTextOutput::testSuitesBegin() {
00420     this->_testSuitesBegin();
00421 
00422     mLogAppender.emitRaw(VSTRING_FORMAT("[status ] Test run starting at %s.", mTestSuitesStartTime.getLocalString().chars()));
00423     mLogAppender.emitRaw(VString::EMPTY());
00424 }
00425 
00426 void VUnitSimpleTextOutput::testSuiteBegin(const VString& testSuiteName) {
00427     this->_testSuiteBegin(testSuiteName);
00428 
00429     mLogAppender.emitRaw(VSTRING_FORMAT("[status ] %s : starting.", testSuiteName.chars()));
00430 }
00431 
00432 void VUnitSimpleTextOutput::testSuiteStatusMessage(const VString& message) {
00433     mLogAppender.emitRaw(VSTRING_FORMAT("[status ] %s : %s", mCurrentTestSuiteName.chars(), message.chars()));
00434 }
00435 
00436 void VUnitSimpleTextOutput::testCaseBegin(const VString& testCaseName) {
00437     this->_testCaseBegin(testCaseName);
00438 }
00439 
00440 void VUnitSimpleTextOutput::testCaseEnd(const VTestInfo& testInfo) {
00441     this->_testCaseEnd(testInfo);
00442 
00443     mLogAppender.emitRaw(VSTRING_FORMAT("[%s] %s : %s.", (testInfo.mSuccess ? "success" : "FAILURE"), mCurrentTestSuiteName.chars(), testInfo.mDescription.chars()));
00444 }
00445 
00446 void VUnitSimpleTextOutput::testSuiteEnd() {
00447     this->_testSuiteEnd();
00448 
00449     mLogAppender.emitRaw(VSTRING_FORMAT("[status ] %s : ended.", mCurrentTestSuiteName.chars()));
00450     mLogAppender.emitRaw(VSTRING_FORMAT("[results] %s : tests passed: %d", mCurrentTestSuiteName.chars(), mCurrentTestSuiteNumSuccesses));
00451     mLogAppender.emitRaw(VSTRING_FORMAT("[results] %s : tests failed: %d", mCurrentTestSuiteName.chars(), mCurrentTestSuiteNumErrors));
00452     mLogAppender.emitRaw(VSTRING_FORMAT("[results] %s : summary: %s.", mCurrentTestSuiteName.chars(), ((mCurrentTestSuiteNumErrors == 0) ? "success" : "FAILURE")));
00453     mLogAppender.emitRaw(VString::EMPTY());
00454 }
00455 
00456 void VUnitSimpleTextOutput::testSuitesEnd() {
00457     mLogAppender.emitRaw(VSTRING_FORMAT("[results] TOTAL tests passed: %d", mTotalNumSuccesses));
00458     mLogAppender.emitRaw(VSTRING_FORMAT("[results] TOTAL tests failed: %d", mTotalNumErrors));
00459     mLogAppender.emitRaw(VSTRING_FORMAT("[results] TOTAL summary: %s.", ((mTotalNumErrors == 0) ? "success" : "FAILURE")));
00460 
00461     if (mFailedTestSuiteNames.size() != 0) {
00462         VString names;
00463         for (VStringVector::const_iterator i = mFailedTestSuiteNames.begin(); i != mFailedTestSuiteNames.end(); ++i) {
00464             names += ' ';
00465             names += *i;
00466         }
00467         mLogAppender.emitRaw(VSTRING_FORMAT("[results] Names of suites with failures:%s", names.chars()));
00468     }
00469 
00470     VInstant now;
00471     VDuration totalTestTime = now - mTestSuitesStartTime;
00472     mLogAppender.emitRaw(VString::EMPTY());
00473     mLogAppender.emitRaw(VSTRING_FORMAT("[status ] Test run ending at %s. Total time %s.", now.getLocalString().chars(), totalTestTime.getDurationString().chars()));
00474 }
00475 
00476 // VUnitTeamCityOutput -------------------------------------------------------
00477 
00478 static VString _escapeTeamCityString(const VString& original) {
00479     VString result = original;
00480 
00481     result.replace("|", "||");
00482     result.replace("'", "|'");
00483     result.replace("\n", "|\n");
00484     result.replace("\r", "|\r");
00485     result.replace("]", "|]");
00486 
00487     return result;
00488 }
00489 
00490 VUnitTeamCityOutput::VUnitTeamCityOutput(VLogAppender& outputAppender) :
00491     VUnitOutputWriter(outputAppender) {
00492 }
00493 
00494 void VUnitTeamCityOutput::testSuitesBegin() {
00495     this->_testSuitesBegin();
00496 }
00497 
00498 void VUnitTeamCityOutput::testSuiteBegin(const VString& testSuiteName) {
00499     this->_testSuiteBegin(testSuiteName);
00500 
00501     mLogAppender.emitRaw(VSTRING_FORMAT("##teamcity[testSuiteStarted name='%s']", _escapeTeamCityString(testSuiteName).chars()));
00502 }
00503 
00504 void VUnitTeamCityOutput::testSuiteStatusMessage(const VString& /*message*/) {
00505 }
00506 
00507 void VUnitTeamCityOutput::testCaseBegin(const VString& testCaseName) {
00508     this->_testCaseBegin(testCaseName);
00509 
00510     mLogAppender.emitRaw(VSTRING_FORMAT("##teamcity[testStarted name='%s']", _escapeTeamCityString(testCaseName).chars()));
00511 }
00512 
00513 void VUnitTeamCityOutput::testCaseEnd(const VTestInfo& testInfo) {
00514     this->_testCaseEnd(testInfo);
00515 
00516     if (!testInfo.mSuccess)
00517         mLogAppender.emitRaw(VSTRING_FORMAT("##teamcity[testFailed name='%s' message='%s']", _escapeTeamCityString(mCurrentTestCaseName).chars(), _escapeTeamCityString(testInfo.mDescription).chars()));
00518 
00519     mLogAppender.emitRaw(VSTRING_FORMAT("##teamcity[testFinished name='%s']", _escapeTeamCityString(mCurrentTestCaseName).chars()));
00520 }
00521 
00522 void VUnitTeamCityOutput::testSuiteEnd() {
00523     this->_testSuiteEnd();
00524 
00525     mLogAppender.emitRaw(VSTRING_FORMAT("##teamcity[testSuiteFinished name='%s']", _escapeTeamCityString(mCurrentTestSuiteName).chars()));
00526 }
00527 
00528 void VUnitTeamCityOutput::testSuitesEnd() {
00529 }
00530 
00531 // VUnitTeamCityBuildStatusOutput --------------------------------------------
00532 
00533 VUnitTeamCityBuildStatusOutput::VUnitTeamCityBuildStatusOutput(VLogAppender& outputAppender) :
00534     VUnitOutputWriter(outputAppender) {
00535 }
00536 
00537 void VUnitTeamCityBuildStatusOutput::testSuitesBegin() {
00538     this->_testSuitesBegin();
00539 }
00540 
00541 void VUnitTeamCityBuildStatusOutput::testSuiteBegin(const VString& testSuiteName) {
00542     this->_testSuiteBegin(testSuiteName);
00543 }
00544 
00545 void VUnitTeamCityBuildStatusOutput::testSuiteStatusMessage(const VString& /*message*/) {
00546 }
00547 
00548 void VUnitTeamCityBuildStatusOutput::testCaseBegin(const VString& testCaseName) {
00549     this->_testCaseBegin(testCaseName);
00550 }
00551 
00552 void VUnitTeamCityBuildStatusOutput::testCaseEnd(const VTestInfo& testInfo) {
00553     this->_testCaseEnd(testInfo);
00554 }
00555 
00556 void VUnitTeamCityBuildStatusOutput::testSuiteEnd() {
00557     this->_testSuiteEnd();
00558 }
00559 
00560 void VUnitTeamCityBuildStatusOutput::testSuitesEnd() {
00561     try {
00562         mLogAppender.emitRaw(VString("<build number=\"{build.number}\">"));
00563         mLogAppender.emitRaw(VSTRING_FORMAT(" <statusInfo status=\"%s\">", (mTotalNumErrors == 0 ? "SUCCESS" : "FAILURE")));
00564         mLogAppender.emitRaw(VSTRING_FORMAT("  <text action=\"append\">Tests passed: %d</text>", mTotalNumSuccesses));
00565         mLogAppender.emitRaw(VSTRING_FORMAT("  <text action=\"append\">Tests failed: %d</text>", mTotalNumErrors));
00566 
00567         if (mFailedTestSuiteNames.size() != 0) {
00568             VString names;
00569             for (VStringVector::const_iterator i = mFailedTestSuiteNames.begin(); i != mFailedTestSuiteNames.end(); ++i) {
00570                 names += ' ';
00571                 names += *i;
00572             }
00573 
00574             mLogAppender.emitRaw(VSTRING_FORMAT("  <text action=\"append\">These are the names of the failed tests:%s</text>", names.chars()));
00575         }
00576 
00577         mLogAppender.emitRaw(VString(" </statusInfo>"));
00578 
00579         mLogAppender.emitRaw(VSTRING_FORMAT(" <statisticValue key=\"testCount\" value=\"%d\"/>", mTotalNumSuccesses + mTotalNumErrors));
00580         mLogAppender.emitRaw(VSTRING_FORMAT(" <statisticValue key=\"testsPassed\" value=\"%d\"/>", mTotalNumSuccesses));
00581         mLogAppender.emitRaw(VSTRING_FORMAT(" <statisticValue key=\"testsFailed\" value=\"%d\"/>", mTotalNumErrors));
00582 
00583         mLogAppender.emitRaw(VString("</build>"));
00584     } catch (...) {} // prevent exceptions from escaping destructor
00585 }
00586 

Copyright ©1997-2014 Trygve Isaacson. All rights reserved. This documentation was generated with Doxygen.