testFixture.h
Go to the documentation of this file.00001
00015 #ifndef _DLR_TESTFIXTURE_H_
00016 #define _DLR_TESTFIXTURE_H_
00017
00018 #include <iostream>
00019 #include <sstream>
00020 #include <string>
00021 #include <vector>
00022
00023 #include <dlrTest/runnableObject.h>
00024 #include <dlrTest/testException.h>
00025 #include <dlrTest/testMacros.h>
00026
00027 namespace dlr {
00028
00029 namespace test {
00030
00069 template <class FixtureType>
00070 class TestFixture
00071 : public RunnableObject
00072 {
00073 public:
00074
00075
00076
00081 typedef FixtureType TestFixtureType;
00082
00088 typedef void (FixtureType::* TestFunctionPtr)();
00089
00090
00091
00092
00100 explicit
00101 TestFixture(const std::string& testFixtureName);
00102
00103
00108 virtual
00109 ~TestFixture();
00110
00111
00126 virtual void
00127 registerTest(const std::string& testName,
00128 TestFunctionPtr testFunctionPtr);
00129
00138 virtual bool
00139 run();
00140
00141 protected:
00142
00143
00144
00151 virtual void
00152 announceTestFinish();
00153
00160 virtual void
00161 announceTestStart();
00162
00163
00188 virtual std::string
00189 buildFailureMessage(size_t failureIndex,
00190 const std::string& testName,
00191 const std::string& failureType,
00192 const std::string& whatMessage);
00193
00194
00205 void
00206 printTestStatistics(int errorCount,
00207 const std::vector<std::string>& testMessages);
00208
00218 virtual void
00219 setUp(const std::string&) {}
00220
00230 virtual void
00231 tearDown(const std::string&) {}
00232
00233
00234
00235
00240 int m_textOutputLineLength;
00241
00246 int m_verbosity;
00247
00248 private:
00249
00250
00251
00252
00253
00254
00255 std::string m_testFixtureName;
00256 std::vector<TestFunctionPtr> m_testFunctionPtrVector;
00257 std::vector<std::string> m_testNameVector;
00258 };
00259
00260 }
00261
00262 }
00263
00264
00265
00266
00267 namespace dlr {
00268
00269 using test::TestFixture;
00270
00271 }
00272
00273
00274
00275
00276
00277
00278
00279
00280 namespace dlr {
00281
00282 namespace test {
00283
00284
00285
00286 template <class FixtureType>
00287 TestFixture<FixtureType>::
00288 TestFixture(const std::string& testFixtureName)
00289 : RunnableObject(),
00290 m_textOutputLineLength(75),
00291 m_verbosity(1),
00292 m_testFixtureName(testFixtureName),
00293 m_testFunctionPtrVector(),
00294 m_testNameVector()
00295 {
00296
00297 }
00298
00299
00300
00301
00302 template <class FixtureType>
00303 TestFixture<FixtureType>::
00304 ~TestFixture()
00305 {
00306
00307 }
00308
00309
00310
00311
00312 template <class FixtureType>
00313 void
00314 TestFixture<FixtureType>::
00315 registerTest(const std::string& testName,
00316 typename TestFixture<FixtureType>::TestFunctionPtr testFunctionPtr)
00317 {
00318 m_testNameVector.push_back(testName);
00319 m_testFunctionPtrVector.push_back(testFunctionPtr);
00320 }
00321
00322
00323
00324
00325
00326 template <class FixtureType>
00327 bool
00328 TestFixture<FixtureType>::
00329 run()
00330 {
00331
00332 this->announceTestStart();
00333
00334
00335 std::vector<std::string> testMessages;
00336
00337
00338
00339 int errorCount = 0;
00340
00341
00342 for(size_t index = 0; index < m_testFunctionPtrVector.size(); ++index) {
00343
00344 try {
00345 this->setUp(m_testNameVector[index]);
00346 } catch(const std::exception&) {
00347
00348
00349 throw;
00350 }
00351
00352
00353 TestFunctionPtr testFunctionPtr = m_testFunctionPtrVector[index];
00354 try {
00355
00356 FixtureType* subclassThis = dynamic_cast<FixtureType*>(this);
00357 (subclassThis->*testFunctionPtr)();
00358
00359 std::cout << "." << std::flush;
00360
00361 } catch(const TestException& caughtException) {
00362
00363
00364
00365 std::cout << "F" << std::flush;
00366
00367
00368 std::string message = this->buildFailureMessage(
00369 testMessages.size() + 1, m_testNameVector[index], "Failed test",
00370 caughtException.what());
00371 testMessages.push_back(message);
00372
00373 } catch(const std::exception& caughtException) {
00374
00375
00376 std::cout << "E" << std::flush;
00377
00378
00379 ++errorCount;
00380
00381
00382 std::string message = this->buildFailureMessage(
00383 testMessages.size() + 1, m_testNameVector[index], "Error in test",
00384 caughtException.what());
00385 testMessages.push_back(message);
00386
00387 } catch(...) {
00388
00389
00390 std::cout << "E" << std::flush;
00391
00392
00393 ++errorCount;
00394
00395
00396 std::string message = this->buildFailureMessage(
00397 testMessages.size() + 1, m_testNameVector[index], "Error in test",
00398 "Unrecognized exception");
00399 testMessages.push_back(message);
00400 }
00401
00402
00403 try {
00404 this->tearDown(m_testNameVector[index]);
00405 } catch(const std::exception&) {
00406
00407
00408 throw;
00409 }
00410
00411
00412
00413 if((index % m_textOutputLineLength == 0)
00414 && (index != 0)) {
00415 std::cout << std::endl;
00416 }
00417 }
00418
00419
00420 this->printTestStatistics(errorCount, testMessages);
00421
00422
00423 this->announceTestFinish();
00424 return (testMessages.size() == 0);
00425 }
00426
00427
00428
00429
00430 template <class FixtureType>
00431 void
00432 TestFixture<FixtureType>::
00433 announceTestFinish()
00434 {
00435 if(m_verbosity >= 3) {
00436 std::cout << "/////////////////////////////////////////////////////\n"
00437 << "// Completed test: " << m_testFixtureName << "\n"
00438 << "/////////////////////////////////////////////////////\n"
00439 << std::endl;
00440 }
00441 }
00442
00443
00444
00445
00446 template <class FixtureType>
00447 void
00448 TestFixture<FixtureType>::
00449 announceTestStart()
00450 {
00451 if(m_verbosity >= 1) {
00452 std::cout << "/////////////////////////////////////////////////////\n"
00453 << "// Starting test: " << m_testFixtureName << "\n"
00454 << "/////////////////////////////////////////////////////\n"
00455 << std::endl;
00456 }
00457 }
00458
00459
00460
00461
00462 template <class FixtureType>
00463 std::string
00464 TestFixture<FixtureType>::
00465 buildFailureMessage(size_t failureIndex,
00466 const std::string& testName,
00467 const std::string& failureType,
00468 const std::string& whatMessage)
00469 {
00470
00471 std::ostringstream messageBuffer;
00472
00473
00474 messageBuffer << failureIndex << ") ";
00475
00476
00477
00478 size_t indentSize = messageBuffer.str().size();
00479
00480
00481 messageBuffer << failureType << " " << m_testFixtureName << "::"
00482 << testName;
00483
00484
00485
00486 std::string::size_type currentIndex = 0;
00487 std::string::size_type chunkSize = m_textOutputLineLength - indentSize;
00488
00489 std::string whitespace = " \t\n";
00490 while(currentIndex < whatMessage.size()) {
00491
00492 messageBuffer << "\n";
00493 for(size_t index = 0; index < indentSize; ++index) {
00494 messageBuffer << " ";
00495 }
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507 std::string::size_type whitespaceIndex = currentIndex;
00508 std::string::size_type nextWhitespaceIndex = currentIndex;
00509 if(whatMessage.size() - currentIndex > chunkSize) {
00510 while(nextWhitespaceIndex <= currentIndex + chunkSize) {
00511 whitespaceIndex = nextWhitespaceIndex;
00512 nextWhitespaceIndex =
00513 whatMessage.find_first_not_of(whitespace, whitespaceIndex);
00514 if(nextWhitespaceIndex == std::string::npos) {
00515 break;
00516 }
00517 nextWhitespaceIndex =
00518 whatMessage.find_first_of(whitespace, nextWhitespaceIndex);
00519 }
00520 }
00521
00522
00523 if(whitespaceIndex != currentIndex) {
00524 std::string::size_type localChunkSize = whitespaceIndex - currentIndex;
00525 messageBuffer << whatMessage.substr(currentIndex, localChunkSize);
00526 currentIndex += localChunkSize + 1;
00527 } else {
00528 messageBuffer << whatMessage.substr(currentIndex, chunkSize);
00529 currentIndex += chunkSize;
00530 }
00531 }
00532
00533
00534 return messageBuffer.str();
00535 }
00536
00537
00538
00539
00540 template <class FixtureType>
00541 void
00542 TestFixture<FixtureType>::
00543 printTestStatistics(int errorCount,
00544 const std::vector<std::string>& testMessages)
00545 {
00546
00547 std::cout << "\n\n";
00548 std::cout << "Test Results:\n"
00549 << "Run: " << m_testFunctionPtrVector.size()
00550 << " \tFailures: " << testMessages.size() - errorCount
00551 << " \tErrors: " << errorCount << "\n" << std::endl;
00552
00553
00554 for(size_t index = 0; index < testMessages.size(); ++index) {
00555 std::cout << testMessages[index] << std::endl;
00556 std::cout << std::endl;
00557 }
00558 }
00559
00560 }
00561
00562 }
00563
00564 #endif // #ifdef _DLR_TESTFIXTURE_H_