I have a program written in C++ and to make sure we don't break anything when making a change I would like to add unit tests.

In the program we used macros to create certain objects that are frequently used. This would look like:

#define PROPERTY_SWITCHPOINT(var) \
private: \
   comp::SwitchPoint* m##var; \
public: \
   void set##var(bool val, unsigned short switchIdx = 0) \
   {\
      if(m##var)  m##var->setValue(val,switchIdx); \
   }\
   bool get##var() \
   {\
      return (NULL == m##var ? false : m##var->getValue()); \
   }\
   comp::SwitchPoint* get##var##Ptr() \
   {\
      return m##var; \
   }

In the header of the class that contains the switchpoints we call the macro

class Classname
{
    private:
        PROPERTY_SWITCHPOINT(SwitchpointObject)
}

In the constructor of the class that contains the switchpoints we then do:

Classname::Classname()
{
    mSwitchpointObject = CreateSwitchpoint("Switchpoint name", 2);
}

comp::SwitchPoint* Classname::CreateSwitchpoint(const std::string& name, unsigned short numberOfSwitches = 1)
{
    comp::SwitchPoint* sp = new comp::SwitchPoint(name, true, numberOfSwitches);
    return sp;
}

Now we can use mSwitchpointObject->getValue() to obtain this object's value. All of this works, but I can't manage to create unit tests for it, where I'm using the unittest++ framework. I tried it with this test:

#include "UnitTest++.h"
#include "Classname.h"

namespace
{
    TEST(SwitchpointTest1)
    {
        PROPERTY_SWITCHPOINT(SwitchpointObject)
        mSwitchpointTestVariabele           = CreateSwitchpoint("test switchpoint", 2);
        CHECK_EQUAL(mSwitchpointTestVariabele->getValue(), true);
        //mSwitchpointTestVariabele->setValue(false, 0);
        //CHECK_EQUAL(mSwitchpointTestVariabele->getValue(), false);
        //mSwitchpointTestVariabele->setValue(false, 1);
        //CHECK_EQUAL(mSwitchpointTestVariabele->getValue(), false);
        //mSwitchpointTestVariabele->setValue(true, 0);
        //CHECK_EQUAL(mSwitchpointTestVariabele->getValue(), false);
        //mSwitchpointTestVariabele->setValue(true, 1);
        //CHECK_EQUAL(mSwitchpointTestVariabele->getValue(), true);
    }
}

But that gives me compiler errors:

|  |In member function 'virtual void<unnamed>::TestSwitchpointTest1::RunImpl() const':|
| 9|error: expected primary-expression before 'private'|
| 9|error: expected ';' before 'private'|
| 9|error: expected primary-expression before 'public'|
| 9|error: expected ';' before 'public'|
| 9|error: a function-definition is not allowed here before '{' token|
| 9|error: a function-definition is not allowed here before '{' token|
|10|error: 'mSwitchpointTestVariabele' was not declared in this scope|
|10|error: 'CreateSwitchpoint' was not declared in this scope|
|  |=== Build finished: 8 errors, 0 warnings ===|

I guessed the problem is that the macro creates a part of the code that needs to be tested and the unit test is performed before this part is created, but from Aleguna's reply I understand this can't be the problem.

How should I write a test for code like this?

有帮助吗?

解决方案

I would suggest taking a look at what code is actually generated, since you have a compilation problem, it sounds like the macro is not generating the code you are expecting it to. If you are using windows/VS you can use "cl.exe /E" or in g++/gcc you can use "gcc -E source.cpp" to run the preprocessor and generate the c++ file that will be compiled.

Unit tests can only be run once the code is successfully compiled (and can be tested like you would unit test any other code).

Your unit test code is expanding to this:

 #include "UnitTest++.h"
    #include "Classname.h"

    namespace
    {
        TEST(SwitchpointTest1)
        {
                private:
       comp::SwitchPoint* mSwitchpointObject;
    public:
       void setSwitchpointObject(bool val, unsigned short switchIdx = 0)
           {
              if(mSwitchpointObject)  mSwitchpointObject->setValue(val,switchIdx);
           }
       bool getSwitchpointObject()
       {
          return (NULL == mSwitchpointObject ? false : mSwitchpointObject->getValue()); 
       }
       comp::SwitchPoint* getSwitchpointObject##Ptr() 
       {
          return mSwitchpointObject; 
       }


 mSwitchpointTestVariabele           = CreateSwitchpoint("test switchpoint", 2);
        CHECK_EQUAL(mSwitchpointTestVariabele->getValue(), true);
        //mSwitchpointTestVariabele->setValue(false, 0);
        //CHECK_EQUAL(mSwitchpointTestVariabele->getValue(), false);
        //mSwitchpointTestVariabele->setValue(false, 1);
        //CHECK_EQUAL(mSwitchpointTestVariabele->getValue(), false);
        //mSwitchpointTestVariabele->setValue(true, 0);
        //CHECK_EQUAL(mSwitchpointTestVariabele->getValue(), false);
        //mSwitchpointTestVariabele->setValue(true, 1);
        //CHECK_EQUAL(mSwitchpointTestVariabele->getValue(), true);
    }
}

其他提示

Well the error is pretty obvious

In member function 'virtual void<unnamed>::TestSwitchpointTest1::RunImpl() const':

You can't use private: and public: (which are contained in your macro) keywords in a function body.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top