4

Consider this CPPUNIT test class meant to do the same test (doTest) but with different arguments:

class MyTest : public CPPUNIT_NS::TestFixture
{
  CPPUNIT_TEST_SUITE( MyTest );
  CPPUNIT_TEST( test1 );
  CPPUNIT_TEST( test2 );
  CPPUNIT_TEST( test3 );
  CPPUNIT_TEST_SUITE_END();

public:
  MyTest();

  void test1() { doTest(1); }
  void test2() { doTest(2); }
  void test3() { doTest(3); }

  void doTest( int param );
};
CPPUNIT_TEST_SUITE_REGISTRATION(MyTest);

Is there no way to change that to avoid having to declare test1, test2 and test3, with something like:

class MyTest : public CPPUNIT_NS::TestFixture
{
  CPPUNIT_TEST_SUITE( MyTest );
  CPPUNIT_TEST_PARAM( doTest, 1 ); // CPPUNIT_TEST_PARAM does not exits, it's just to illustrate my need
  CPPUNIT_TEST_PARAM( doTest, 2 ); // CPPUNIT_TEST_PARAM does not exits, it's just to illustrate my need
  CPPUNIT_TEST_PARAM( doTest, 3 ); // CPPUNIT_TEST_PARAM does not exits, it's just to illustrate my need
  CPPUNIT_TEST_SUITE_END();

public:
  MyTest();

  void doTest( int param );
};
CPPUNIT_TEST_SUITE_REGISTRATION(MyTest);

Note that CPPUNIT_TEST is a macro:

#define CPPUNIT_TEST( testMethod )                        \
    CPPUNIT_TEST_SUITE_ADD_TEST(                           \
        ( new CPPUNIT_NS::TestCaller<TestFixtureType>(    \
                  context.getTestNameFor( #testMethod),   \
                  &TestFixtureType::testMethod,           \
                  context.makeFixture() ) ) )

Edit:

Tried this:

CPPUNIT_TEST_SUITE( MyTest );
CPPUNIT_TEST( funcT<1> );
CPPUNIT_TEST_SUITE_END();

template<int i> void funcT() { doTest(i); }

It works fine, but fails if I use char* types:

CPPUNIT_TEST_SUITE( MyTest );
CPPUNIT_TEST( funcT<"foo"> );
CPPUNIT_TEST_SUITE_END();

template<char* s> void funcT() { std::cout << s << std::endl; doTest(1); }

It errors:

error C2664: 'CppUnit::TestCaller<test_cppunit_regulation_regul_dt_100::TestFixtureType>::TestCaller(const CppUnit::TestCaller<test_cppunit_regulation_regul_dt_100::TestFixtureType> &)': cannot convert argument 2 from 'void (__cdecl *)(void)' to 'void (__cdecl test_cppunit_regulation_regul_dt_100::* )(void)'

Or more parameters:

CPPUNIT_TEST_SUITE( MyTest );
CPPUNIT_TEST( funcT<1,2> );
CPPUNIT_TEST_SUITE_END();

template<int i, int j> void funcT() { doTest(i+j); }

It errors:

1>b:\dev\vobs_diabeloop\private\tst\regulation\cppunit\regul_dt_100\test.cpp(14): warning C4002: too many actual parameters for macro 'CPPUNIT_TEST'
1>b:\dev\vobs_diabeloop\private\tst\regulation\cppunit\regul_dt_100\test.cpp(14): error C2059: syntax error: ')'

Finally tried to add parenthesis ( CPPUNIT_TEST( (funcT<1,2>) ); ), it errors:

1>b:\dev\vobs_diabeloop\private\tst\regulation\cppunit\regul_dt_100\test.cpp(14): error C2589: '(': illegal token on right side of '::'
1>b:\dev\vobs_diabeloop\private\tst\regulation\cppunit\regul_dt_100\test.cpp(14): error C2059: syntax error: '::'
1>b:\dev\vobs_diabeloop\private\tst\regulation\cppunit\regul_dt_100\test.cpp(14): error C2660: 'CppUnit::TestSuiteBuilderContextBase::addTest': function does not take 2 arguments
1>b:\dev\vobs_diabeloop\private\tst\regulation\cppunit\regul_dt_100\test.cpp(14): error C2143: syntax error: missing ';' before ')'
1>b:\dev\vobs_diabeloop\private\tst\regulation\cppunit\regul_dt_100\test.cpp(14): error C2059: syntax error: ')'
jpo38
  • 20,821
  • 10
  • 70
  • 151
  • I don't know idiomatic cppunit usage, but would `void test1() { doTest(1); doTest(2); doTest(3); }` help at all? – Mark B Nov 30 '16 at 16:04
  • I need the three tests to be separate to have them all be ran (with your proposal, if the first fails, the two last ones are not executed) – jpo38 Nov 30 '16 at 16:09
  • Look [here](http://stackoverflow.com/questions/5687540/non-type-template-parameters#5687553). You can't use `std::string` there, but `char*` will work. This is a language specification. Could you post the full stack from using a lambda (I forgot to protect it in my answer, fixed now). – kabanus Dec 01 '16 at 09:46
  • @kabanus: Added full error message to your post as an edit. – jpo38 Dec 01 '16 at 10:27

1 Answers1

0

Found a solution by creating several test classes (instead of one single with several sub-tests).

Simple case where there's only one int parameter:

class BaseTest : public CPPUNIT_NS::TestFixture
{
public:
    BaseTest() {}

    void doTest( int param ) {}
};

template < int i >
class MyTest : public BaseTest
{
    CPPUNIT_TEST_SUITE(MyTest<i>);
    CPPUNIT_TEST( doTest );
    CPPUNIT_TEST_SUITE_END();

    void doTest()
    {
        BaseTest::doTest( i );
    };
};

#define REGISTER_TEST_WITH_PARAMS( name, a ) \
        CPPUNIT_TEST_SUITE_REGISTRATION( MyTest<a> );

REGISTER_TEST_WITH_PARAMS( test1, 1 );
REGISTER_TEST_WITH_PARAMS( test2, 2 );

If more parameters are needed, just create a class to encapsulate them:

class BaseTest : public CPPUNIT_NS::TestFixture
{
public:
    BaseTest() {}

    void doTest( int param1, const std::string& param2 ) {}
};

class ParamClass
{
public:
    ParamClass( int param1, const std::string& param2 ) :
        param1( param1 ),
        param2( param2 )
    {

    }

    int param1;
    std::string param2;
};

template < ParamClass & T >
class CURRENT_MODULE : public BaseTest
{
    CPPUNIT_TEST_SUITE(MyTest<T>);
    CPPUNIT_TEST( doTest );
    CPPUNIT_TEST_SUITE_END();

    void doTest()
    {
        BaseTest::doTest( T.param1, T.param2 );
    };
};

#define REGISTER_TEST_WITH_PARAMS( name, a, b ) \
        ParamClass name( a, b ); \
        CPPUNIT_TEST_SUITE_REGISTRATION( MyTest<name> );

REGISTER_TEST_WITH_PARAMS( test1, 1, "test1" );
REGISTER_TEST_WITH_PARAMS( test2, 2, "test2" );
jpo38
  • 20,821
  • 10
  • 70
  • 151
  • The next version of cppunit will contain parameterized test cases. Sadly it is not yet clear when it will be released. Hopefully end of the month but there might be some delays. – moggi Dec 08 '16 at 04:54
  • @moggi "next release"? The last release (1.12.2) was made in 2008, so I doubt there is a next release coming soon.... – jpo38 Dec 08 '16 at 06:41
  • https://www.freedesktop.org/wiki/Software/cppunit/ is more or less the new home and the version that all linux distros ship. That one is maintained by the LibreOffice team. – moggi Dec 08 '16 at 07:50
  • @moggi: Good to know, I'll try to upgrade to that version some day! Thanx – jpo38 Dec 08 '16 at 07:51