Kicking It Old School

November 8, 2009 § Leave a comment

Sometimes, you just got to do it yourself

Have you ever had to resurrect an old code base because the business needs some new functionality added?  Of course you have.  If you haven’t, wait.  If you have, then you understand the pain you have to go through to get the new features added.  The hard part is not adding the features, it is verifying that the changes do not introduce defects in the existing code.  If the code base is old and without a test framework to support it, you are likely stuck with endless manual testing and a few prayers to back you up.

That’s the situation we found ourselves in recently.  We had a new major feature to add and no test framework to support our efforts.  We tried to leverage a few frameworks including Google Test, but found that we were spending a large portion of time troubleshooting incompatibilities with libraries.  Eventually I concluded that we had to build our own test framework.  We wanted to use an established test framework, but all we needed was a way to perform simple state-based, confirmatory tests, so I felt we could get by without one.

I spent a couple hours last Saturday afternoon prototyping and came up with the following code to kick start our framework.  Since I wrote the prototype I have added UI to present the outcomes & smart pointer support, so it looks like this code will grow to fit our needs.

If you are itching to build your own custom C++ test framework, feel free to build off of this code.  I used Visual Studio and the Boost libraries to built it.

 

   1: #include "stdafx.h"
   2: #include <list>
   3: #include <algorithm>
   4: #include <iostream>
   5: #include "boost/ptr_container/ptr_list.hpp"
   6:  
   7: class TestContract {
   8: public:
   9:     virtual std::string GetName() = 0;
  10:     virtual bool RunTest() = 0;
  11: };
  12:  
  13: class SingleTest : public TestContract
  14: {
  15: public:
  16:     std::string GetName() {
  17:         std::string name ("test 1");
  18:         return name;
  19:     }
  20:     bool RunTest() { return true; }
  21: };
  22:  
  23:  
  24: class TestRunner
  25: {
  26: public:
  27:  
  28:     void AddTest(TestContract* test)
  29:     {
  30:         Tests.push_back(test);
  31:     }
  32:  
  33:     void RunTests()
  34:     {        
  35:         for (    TestsIter = Tests.begin();
  36:                 TestsIter != Tests.end();
  37:                 TestsIter++)
  38:         {
  39:             executeTest(*TestsIter);
  40:         }
  41:     }
  42:  
  43: private:
  44:     
  45:     boost::ptr_list<TestContract> Tests;
  46:     boost::ptr_list<TestContract>::iterator TestsIter;
  47:  
  48:     void executeTest(TestContract& singleTest) {
  49:         
  50:         std::string name (singleTest.GetName());
  51:  
  52:         if (singleTest.RunTest())
  53:         {
  54:             std::cout << name.c_str() << ": passed" << std::endl;
  55:         } else {
  56:             std::cout << name.c_str() << ": failed" << std::endl;
  57:         }
  58:     }
  59: };
  60:  
  61:  
  62: int _tmain(int argc, _TCHAR* argv[])
  63: {
  64:     SingleTest* pSingle = new SingleTest();
  65:     TestRunner* pTestRunner = new TestRunner();    
  66:  
  67:     pTestRunner->AddTest(pSingle);
  68:  
  69:     pTestRunner->RunTests();
  70:  
  71:     return 0;
  72: }

Leave a comment

What’s this?

You are currently reading Kicking It Old School at Journeyman.

meta