Приспичило мне однажды овладеть юнит-тестированием кода C++. Так приспичило, что сил никаких нет - ни есть не могу, ни спать. Прошвырнувшись по ближайшим форумам, я понял, что не один такой, и что страждущих немало, но все они в каких-то непонятках. Казалось бы - чего тут сложного? Ан нет, каждый свое защищает: линуксоиды все как один говорят, что "у них все есть, но виндузятникам этого не понять", виндузятники раскидывают по сторонам слюни, описывая некую приблуду к Visual Studio, а все остальные тихо сидят и посмеиваются. В общем, черт их разберет, кто прав. Единственное название, упоминающееся более-менее часто - это CppUnit.
Вспомнив, как классно было работать с NUnit, я глядел на прогресс-бар скачивания дистрибутива, счастливо улыбаясь и предвкушая легкую жизнь. Но суровая реальность оказалась жестокой - ничего напоминающего мои прошлые опыты с инструментами тестирования я там не нашел.
Началось все с того, что меня заставили компилировать библиотеки самостоятельно. Но то ли авторы не удосужились проверить свое творение на последних версиях Студии, то ли Студия мне попалась кривая, но компиляция у меня шла, спотыкаясь на каждом шагу и ругаясь на чем свет стоит. В результате я все же смог получить нужные либы, правда, только для режима отладки.
Следующим шагом было прочтение readme.txt, который по совместительству является этаким сборником рецептов. Следуя инструкциям, я пытался заставить свои тесты запускаться с помощью GUI-утилиты TestPlugInRunnerd.exe, но потратив на это несколько часов, убедил себя, что GUI - это для маленьких, а настоящие дядьки работают в консоли, на чем и успокоился.
Запустить тесты в консоли оказалось не в пример проще. Ниже приведу последовательность действий, актуальную для Visual Studio 8 (2005).
1) Добавляем каталог include установленного CppUnit в стандартные пути (Tools - Options - Projects and Solutions - VC++ Directories).
2) Добавляем в проект ссылку на cppunitd.lib (в свойствах проекта: Configuration Properties - Linker - Input).
3) Пишем тест примерно такого вида:
4) Пишем функцию main() примерно так:
5) Запускаем и радуемся. Если появляются новые тесты, то для каждого из них (я имею в виду для каждого Test Suite) нужно добавить строку вида CPPUNIT_TEST_SUITE_REGISTRATION(...) в файл с функцией main(). После запуска программа выдаст на консоль информацию о выполненных тестах, и если какие-то из них не прошли, укажет причину ошибок и соответствующие номера строк в исходных файлах.
Вот так, дешево и сердито. Если кто знает, как делать то же самое, но с помощью GUI-утилиты, буду рад у вас сонно поучиться.
Вспомнив, как классно было работать с NUnit, я глядел на прогресс-бар скачивания дистрибутива, счастливо улыбаясь и предвкушая легкую жизнь. Но суровая реальность оказалась жестокой - ничего напоминающего мои прошлые опыты с инструментами тестирования я там не нашел.
Началось все с того, что меня заставили компилировать библиотеки самостоятельно. Но то ли авторы не удосужились проверить свое творение на последних версиях Студии, то ли Студия мне попалась кривая, но компиляция у меня шла, спотыкаясь на каждом шагу и ругаясь на чем свет стоит. В результате я все же смог получить нужные либы, правда, только для режима отладки.
Следующим шагом было прочтение readme.txt, который по совместительству является этаким сборником рецептов. Следуя инструкциям, я пытался заставить свои тесты запускаться с помощью GUI-утилиты TestPlugInRunnerd.exe, но потратив на это несколько часов, убедил себя, что GUI - это для маленьких, а настоящие дядьки работают в консоли, на чем и успокоился.
Запустить тесты в консоли оказалось не в пример проще. Ниже приведу последовательность действий, актуальную для Visual Studio 8 (2005).
1) Добавляем каталог include установленного CppUnit в стандартные пути (Tools - Options - Projects and Solutions - VC++ Directories).
2) Добавляем в проект ссылку на cppunitd.lib (в свойствах проекта: Configuration Properties - Linker - Input).
3) Пишем тест примерно такого вида:
#include <cppunit/TestFixture.h>
#include <cppunit/extensions/HelperMacros.h>
class MyTest : public CppUnit::TestFixture
{
CPPUNIT_TEST_SUITE(MyTest);
CPPUNIT_TEST(myTest1);
CPPUNIT_TEST(myTest2);
CPPUNIT_TEST(myTest3);
CPPUNIT_TEST_SUITE_END();
public:
void setUp() {
// инициализация
}
void tearDown() {
// деинициализация
}
void myTest1() {
CPPUNIT_ASSERT(true);
}
void myTest2() {
CPPUNIT_ASSERT(true);
}
void myTest3() {
CPPUNIT_ASSERT(false && true);
}
};
4) Пишем функцию main() примерно так:
#include <cppunit/ui/text/TestRunner.h>
#include "MyTest.h"
CPPUNIT_TEST_SUITE_REGISTRATION(MyTest);
int main()
{
CppUnit::TextUi::TestRunner runner;
CppUnit::TestFactoryRegistry ®istry = CppUnit::TestFactoryRegistry::getRegistry();
runner.addTest( registry.makeTest() );
runner.run();
return 0;
}
5) Запускаем и радуемся. Если появляются новые тесты, то для каждого из них (я имею в виду для каждого Test Suite) нужно добавить строку вида CPPUNIT_TEST_SUITE_REGISTRATION(...) в файл с функцией main(). После запуска программа выдаст на консоль информацию о выполненных тестах, и если какие-то из них не прошли, укажет причину ошибок и соответствующие номера строк в исходных файлах.
Вот так, дешево и сердито. Если кто знает, как делать то же самое, но с помощью GUI-утилиты, буду рад у вас сонно поучиться.
14 комментариев:
Сранно что этот блог никто не читает. Очень даже понравилоль, и помогло с CppUnit. Спасиб...
На здоровье! Постараюсь почаще сюда писать.
Ошибочка !!!
int main()
{
CppUnit::TextUi::TestRunner runner;
CppUnit::TestFactoryRegistry ®istry = CppUnit::TestFactoryRegistry::getRegistry();
runner.addTest( registry.makeTest() );
runner.run();
return 0;
}
Что должно быть?
Какая ошибочка-то?
®istry Что должно быть
Хм, должно быть ®istry, как в статье и написано. Что-то я не понимаю, в чем проблема, уж извините меня...
®istry
Первый символ переменной стоит ® код в юникоде U+00AE (буква R в кружочке)
Я написал registry выдал тучу ошибок( vc6.0)
msvcprtd.lib(MSVCP60D.dll) : error LNK2005: "public: __thiscall std::basic_string......(void)" (??1?$basic_strin
g@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ) already defined in test1.obj
видимо чтото чтото DLL
Это ошибка линкера, имя переменной тут не при чем. Вообще, не уверен, что использование в программе символов с кодами больше 127 - хорошая мысль.
Я по-прежнему с трудом понимаю. Вы в своей программе назвали переменную ®istry, и программа перестала работать? Или же Вы в моей статье видите ®istry как ®istry?
Я вижу в статье букву R в кружочке ®istry как ®istry.
Вот теперь понял. В статье вместо ®istry на самом деле написан символ амперсанда & и слово registry. Я это вижу именно так (Firefox 2.0.0.6).
Статью исправил, теперь должно отображаться нормально.
А это что?
CPPUNIT_ASSERT(false && true);
как использовать cppunit для написания модульных тестов в VS2012?
"Если появляются новые тесты, то для каждого из них (я имею в виду для каждого Test Suite) нужно добавить строку вида CPPUNIT_TEST_SUITE_REGISTRATION(...) в файл с функцией main()"
Можно делать и так, но если проще, то макрос CPPUNIT_TEST_SUITE_REGISTRATION(MyTest) можно подключить в MyTest.cpp перед определением класса.
И делать так каждый раз при добавлении новых тестов. Таким образом можно избавиться от необходимости каждый раз дописывать main.
Так же отпадает необходимость инклудить новый тест в main файле.
g++ -o test -I/usr/include -L/usr/lib/x86_64-linux-gnu/ -lcppunit testCppUnit.cpp
testCppUnit.cpp: In function ‘int main()’:
testCppUnit.cpp:17:23: error: no matching function for call to ‘CppUnit::TextTestRunner::addTest(int*)’
runner.addTest(&test);
^
testCppUnit.cpp:17:23: note: candidate is:
In file included from /usr/include/cppunit/ui/text/TextTestRunner.h:7:0,
from testCppUnit.cpp:2:
/usr/include/cppunit/TestRunner.h:85:16: note: virtual void CppUnit::TestRunner::addTest(CppUnit::Test*)
virtual void addTest( Test *test );
^
/usr/include/cppunit/TestRunner.h:85:16: note: no known conversion for argument 1 from ‘int*’ to ‘CppUnit::Test*’
Отправить комментарий