Running re-test reporting as various tests

I would like to unit test a function with a bunch of different inputs and expected outputs.

My function doesn't matter, so instead I use an example function that takes into account English words with the following candidate implementation:

int countEnglishWords( const std::string& text )
{
  return 5;
};

      

The next is a set of test data. The end of the data is marked with an element with the word "END".

struct TestData {
  std::string text;
  int englishWords;
};

struct TestData data[] = // Mark end with "END"
{
  { "The car is very fast", 5 },
  { "El coche es muy rapido", 0 },
  { "The rain in Spain stays mainly in the plain", 9},
  { "XXXXX OOOOO TTTT", 0},
  { "Yes Si No No", 3},
  { "I have a cheerful live", 5},
  { "END", 0}
};

      

I could easily write 6 test cases and I would get the result I want. But this is not supported as any additional tests added to the test cases will not be validated, this will require another test case which will be just the boiler plate. Thus, I wrote one test case that validates all test data like this:

#include <cppunit/ui/text/TestRunner.h>
#include <cppunit/extensions/HelperMacros.h>

class cppUnit_test: public CppUnit::TestFixture
{
private:
   CPPUNIT_TEST_SUITE (cppUnit_test);
   CPPUNIT_TEST(myTest);
   CPPUNIT_TEST_SUITE_END();

public:
   void myTest();
};

void cppUnit_test::myTest()
{
  TestData* p = data;
  while ( p->text != "END")
  {
    std::stringstream ss;
    ss << "Text=\"" << p->text << "\" Counted=" << 
       countEnglishWords(p->text) << " Expected=" << p->englishWords;
    CPPUNIT_ASSERT_MESSAGE( ss.str().c_str(), 
                countEnglishWords(p->text) == p->englishWords );
    ++p;
  }
}

int main()
{
   CPPUNIT_TEST_SUITE_REGISTRATION (cppUnit_test);
   CppUnit::Test *suite =
         CppUnit::TestFactoryRegistry::getRegistry().makeTest();
   CppUnit::TextUi::TestRunner runner;
   runner.addTest(suite);
   runner.run();
   return 0;
}

      

The problem is that the previous code goes through the 1st test tone and also finds an error in the second test, but after that it stops testing. And the report:

!!! CRASH!!!
Test Results:
Run: 1 Failures: 1 Errors: 0

Whereas the result I would like to get is:

!!! CRASH!!!
Test Results:
Run: 6 Failures: 4 Errors: 0

+3


source to share


1 answer


As I mentioned in the comment, cppunit 1.14.0 can support your use case.

I want to reference an external array, the fastest way is to use CPPUNIT_TEST_PARAMETERIZED. This macro expects two parameters: first, similarly to CPPUNIT_TEST - a test method, and then as a second parameter - an iterative one.

Based on your code, it looks like this:

CPPUNIT_TEST_PARAMETERIZED(myTest, aData);

      

Now we need to adapt your myTest function a bit.



void cppUnit_test::myTest(const TestData& data)
{
    std::stringstream ss; 
    ss << "Text=\"" << data.text << "\" Counted=" <<  
        countEnglishWords(data.text) << " Expected=" << data.englishWords;

    bool b = countEnglishWords(data.text) == data.englishWords;
    std::string a = ss.str();
    CPPUNIT_ASSERT_MESSAGE( a,  
            b); 
}

      

Finally, since the framework needs a way to tell which test failed, it expects it to be able to print the parameter that is passed to the test function. In this case, the simplest way is to add a simple <<operator overload.

std::ostream& operator<<(std::ostream& strm, const TestData& data)
{
    strm << data.text;
    return strm;
}

      

If you combine these chunks, you should quickly get a general solution that allows you to add as much data to your dataset as you want without having to tweak your test code.

+1


source







All Articles