Библиотеки модульного тестирования C++
Я сталкивался с cppunit, но он не выглядел супер-простым в использовании (может быть, я не выглядел жестко, может быть, потому что C++ не работает как Java/C#). Есть ли широко используемые простые альтернативы?
Фактически, является ли cppunit стандартной структурой модульного тестирования для C++?
8 ответов
Для C++ нет стандартной библиотеки модульного тестирования. Есть много вариантов на выбор; Cppunit является одним из них.
В моей компании мы используем Google Test вместе со своим партнером Google Mock для модульного тестирования и моделирования объектов. Я нахожу их обоих более простыми в использовании и намного более мощными, чем cppunit.
Я только что выдвинул свою собственную структуру, CATCH, там. Он все еще находится в стадии разработки, но я считаю, что он уже превосходит большинство других структур. У разных людей разные критерии, но я старался охватить большинство вопросов без слишком большого количества компромиссов. Взгляните на мою связанную запись в блоге для дегустатора. Мои пять лучших функций:
- Только заголовок
- Автоматическая регистрация функциональных и методических тестов
- Разлагает стандартные выражения C++ на LHS и RHS (поэтому вам не нужно целое семейство макросов assert).
- Поддержка вложенных секций в функциональном приспособлении
- Проверка имен с использованием естественного языка - генерируются имена функций / методов
Он также имеет привязки Objective-C.
В качестве примера, вот как вы бы написали эквивалент примера gtest, который цитировал @dmeister:
TEST_CASE( "Factorial/Handles zero input", "Tests factorial of 0.")
{
REQUIRE( Factorial(0) == 1 );
}
TEST_CASE( "Factorial/Handles positive input", "Tests factorial of positive numbers.")
{
REQUIRE( Factorial(1) == 1 );
REQUIRE( Factorial(2) == 2 );
REQUIRE( Factorial(3) == 6 );
REQUIRE( Factorial(8) == 40320 );
}
Если тест не пройден, вы все равно получите значения LHS и RHS, записанные независимо.
Google Test Framework является альтернативой.
Вот простой пример из документации:
// Tests factorial of 0.
TEST(FactorialTest, HandlesZeroInput) {
EXPECT_EQ(1, Factorial(0));
}
// Tests factorial of positive numbers.
TEST(FactorialTest, HandlesPositiveInput) {
EXPECT_EQ(1, Factorial(1));
EXPECT_EQ(2, Factorial(2));
EXPECT_EQ(6, Factorial(3));
EXPECT_EQ(40320, Factorial(8));
}
Это также хорошо работает с gmock, фиктивной платформой Google для C++.
Я создал набор тестов под названием saru ( http://github.com/mikeando/saru) для своего собственного кода разработчика. Это лицензионный код BSD. Я разработал его, так как мне не нравились некоторые особенности других наборов тестирования. Он не очень широко используется, но я использовал его в нескольких коммерческих проектах, распределенных между двумя компаниями.
- Мне не нравится, когда все мои тесты собираются в один бинарный файл. Мои причины для этого состоят в том, что если компиляция не проходит, все тесты не выполняются, если один тест выполняет неопределенное поведение, вывод программы не определен.
- Я хочу контролировать, какие тесты запускаются. Я хочу иметь возможность группировать тесты и запускать подмножества.
- Я хочу, чтобы о сбое компиляции теста сообщалось как о неудаче теста, а не о прекращении всех моих тестов.
- Я хочу иметь возможность запускать тесты на разных языках
- Я хочу, чтобы система была достаточно гибкой, чтобы я мог запускать определенные тесты под valgrind (пока нет в saru:()
Итак, Сару обращается к большинству этих функций. Он сосредоточен на возможности запуска набора тестов, написанных на разных языках. С минимальными размерами теста. Вот самый маленький (провальный) тест C++
//SARU : dummy dummy
int main() { return (1==2)?0:1; }
Все, что действительно волнует saru - это возвращаемое значение двоичного файла, который он компилирует. Затем он анализирует выходные данные, чтобы определить, какие тесты не пройдены и так далее. У него есть заголовки, чтобы сделать работу с C++ немного лучше, чем приведенный выше тривиальный пример:
//SARU : dummy dummy
#include "MyStruct.h"
#include "saru_cxx.h"
class Fixture
{
MyStruct s_;
Fixture() : s_() {}
void test_A_is_B()
{
SARU_ASSERT_EQUAL( s_.A(), s_.B() );
}
void test_C_is_7()
{
SARU_ASSERT_EQUAL( 7, s_.C() );
}
};
int main()
{
saru::TestLogger logger;
SARU_TEST( Fixture:: test_A_is_B, logger );
SARU_TEST( Fixture:: test_C_is_7, logger );
logger.printSummary();
return logger.allOK()?0:1;
}
Или, если вам не нравится, как работают его заголовки C++, он должен быть в состоянии интегрироваться с другими библиотеками для тестирования модулей с минимальными трудностями.
Но он также будет запускать тесты, написанные на PHP и Python. Таким образом, вы можете настроить полные функциональные тесты с SARU. Или вы можете запустить что-то вроде lint поверх своего кода как часть набора тестов.
CppUnit, вероятно, является первым модульным тестовым фреймворком для C++. Это прямой порт Junit, знаменитой платформы Java. Это облегчает переход с Junit, но за счет довольно тяжелой среды, которая не использует возможности C++, такие как RAII. Вот почему были созданы легкие версии, такие как CppUnitLite, NanoCppUnit. CppUnit2 должен был улучшить это, среди других улучшений.
Тут раньше было очень легко, всего один заголовок, но в последних версиях появилась библиотека.
Что касается "стандартного" фреймворка, то его нет, и C++1X не определяет его.
Вот минимальная библиотека модульного тестирования C++: https://github.com/vahidk/minimal-cpp-test
Он имеет синтаксис, очень похожий на библиотеку тестов Google, но это библиотека только для заголовков, поэтому его проще переносить на разные платформы.
Вот минимальный юнит-тест:
#define DEFINE_TEST_MAIN
#include "test.h"
TEST(GroupName, TestName) {
EXPECT_EQ(1 + 2, 3);
}
И минимальное крепление:
class ClassName : public cyrus:Test {
public:
void Setup() override {
x = 5;
}
int x;
}
Test_F(ClassName, Test1) {
EXPECT_EQ(x, 5);
}
Надеюсь это поможет.
Вот один заголовочный файл, включающий только решение для модульного тестирования C++: https://gitlab.com/cppocl/unit_test_framework
Простой пример использования здесь, но у него также есть приспособления (настройка и разборка), неудачный тест на утечку памяти, неудачный тест на производительность (я больше нигде не видел эту функцию).
#include "test/Test.hpp"
TEST(MyTest)
{
int a = 1;
int b = 2;
CHECK_EQUAL(a + b, 3);
}
Вот список библиотек модульного тестирования.
http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks
Однако, насколько я знаю, cppunit - самый популярный.