У меня есть программа, написанная на C ++, и чтобы убедиться, что мы ничего не нарушаем при внесении изменений, я хотел бы добавить модульные тесты.
В программе мы использовали макросы для создания определенных объектов, которые часто используются. Это будет выглядеть так:
#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; \
}
В заголовке класса, который содержит точки переключения, мы называем макрос
class Classname
{
private:
PROPERTY_SWITCHPOINT(SwitchpointObject)
}
В конструкторе класса, который содержит точки переключения, мы затем делаем:
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;
}
Теперь мы можем использовать mSwitchpointObject->getValue()
чтобы получить значение этого объекта. Все это работает, но я не могу создать для него модульные тесты, где я использую инфраструктуру unittest ++.
Я попробовал это с этим тестом:
#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);
}
}
Но это дает мне ошибки компилятора:
| |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 ===|
Я догадался, что проблема в том, что макрос создает часть кода, которую нужно протестировать, и модульное тестирование выполняется до того, как эта часть будет создана, но из ответа Алегуны я понимаю, что это не может быть проблемой.
Как мне написать тест для такого кода?
Я бы посоветовал взглянуть на то, какой код генерируется на самом деле, поскольку у вас есть проблема с компиляцией, похоже, что макрос не генерирует код, который вы ожидаете. Если вы используете Windows / VS, вы можете использовать «cl.exe / E» или в g ++ / gcc вы можете использовать «gcc -E source.cpp», чтобы запустить препроцессор и сгенерировать файл c ++, который будет скомпилирован.
Модульные тесты могут быть запущены только после успешной компиляции кода (и могут быть протестированы так же, как если бы вы тестировали любой другой код).
Ваш код модульного теста расширяется до этого:
#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);
}
}
Ну, ошибка довольно очевидна
In member function 'virtual void<unnamed>::TestSwitchpointTest1::RunImpl() const':
Вы не можете использовать private:
а также public:
(которые содержатся в вашем макросе) ключевые слова в теле функции.