TinyUnit++ - это минималистичная система unit тестирования для C++. Особенности и функции:
- Исходный код представлен двумя файлами.
- Виды assert'ов:
- Проверка на равенство или неравенство двух переменных.
- Проверка булевых переменных и выражений.
- Проверка на равенство двух значений с плавающей точкой (с некоторым допуском).
- Возможность добавить произвольное сообщение к любым assert'ам.
- Возможность вывести любое сообщение.
- Представляет из себя библиотеку, что позволяет встраивать систему куда угодно.
- Режим пропуска ошибочных assert'ов.
- Режим запуска указанных через командную строку тестов.
- Несколько вариантов тихого режима (без вывода в консоль результатов, но поднятия %ERRORLEVEL% в случае неудачного прохождения тестов).
- Система не имеет зависимостей, кроме стандартной библиотеки C++.
Система изначально создавалась для личных целей, как библиотека, которую можно встроить в разные проекты целиком, дабы не иметь лишних зависимостей. Как плата за такую возможность - отсутствие возможностей, которые имеют другие системы unit тестирования, такие как: развитая система assert'ов, архитектурная поддержка фикстур и mock, иерархические тесты, группировка тестов и другие. Как следствие, если Вам нужно что-то из вышеописанного, данная система Вам не подойдёт.
Создадим папку tupp_example
. В неё положим tupp.cpp
, tupp.h
из папки src
. Далее создадим
в той же папке файл main.cpp
со следующим содержимым:
#include "tupp.hpp"
void example_test_assert()
{
int a = 5;
int b = 5;
int c = 6;
TUPP_MESSAGE("Example assert.");
TUPP_ASSERT(a, b);
TUPP_N_ASSERT(a, c);
}
void example_test_float()
{
float a = 5.0f;
float b = 5.0f;
TUPP_MESSAGE("Example float.");
TUPP_ASSERT_F(a, b);
}
void example_test_bool()
{
bool a = true;
bool b = false;
TUPP_MESSAGE("Example bool.");
TUPP_ASSERT_TRUE(a);
TUPP_ASSERT_FALSE(b);
}
int main(int argc, char* argv[])
{
TUPP_ADD_TEST(example_test_assert);
TUPP_ADD_TEST(example_test_float);
TUPP_ADD_TEST(example_test_bool);
return tupp::run(argc, argv);
}
Дале скомпилируем этот пример командами:
g++ -c ./main.cpp -o ./main.o -std=c++17
g++ -c ./tupp.cpp -o ./tupp.o -std=c++17
g++ ./tupp.o ./main.o -o ./main -std=c++17
Теперь запустим main
. Должны получить следующий результат:
#### START ####
TEST 'example_test_bool': SUCCESS
Message: Example bool. Line: 28
TEST 'example_test_float': SUCCESS
Message: Example float. Line: 19
TEST 'example_test_assert': SUCCESS
Message: Example assert. Line: 9
#### FINISH ####
Run: 3/3, Fail: 0, Pass: 3
TUPP_ASSERT(V_A, V_B, [MSG, [MSG, [...]]]);
Этот макрос позволяет проверить два значения на равенство. Имеет следующие аргументы:
V_A
,V_B
- Сравниваемые значения (или переменные). Тип переменных не имеет значения, главное, чтобы они могли быть сравнимы.MSG
- Дополнительные сообщения (можно задать любое количество: сообщения будут объединены в одно). В качестве сообщения может выступать строка или строковая переменная.
Сгенерирует ошибку, если V_A
не равен V_B
.
Пример:
int a = 5, b = 5, c = 6;
TUPP_ASSERT(a, b, "Exmaple message"); // Пройдёт успешно.
TUPP_ASSERT(a, c); // Будет сгенерирована ошибка.
TUPP_N_ASSERT(V_A, V_B, [MSG, [MSG, [...]]]);
Этот макрос позволяет проверить два значения на неравенство. Имеет следующие аргументы:
V_A
,V_B
- Сравниваемые значения (или переменные). Тип переменных не имеет значения, главное, чтобы они могли быть сравнимы.MSG
- Дополнительные сообщения (можно задать любое количество: сообщения будут объединены в одно). В качестве сообщения может выступать строка или строковая переменная.
Сгенерирует ошибку, если V_A
равен V_B
.
Пример:
int a = 5, b = 5, c = 6;
TUPP_N_ASSERT(a, c, "Exmaple message"); // Пройдёт успешно.
TUPP_N_ASSERT(a, b); // Будет сгенерирована ошибка.
TUPP_ASSERT_TRUE(V, [MSG, [MSG, [...]]]);
Этот макрос позволяет проверить передаваемое булево значение на истину. Имеет следующие аргументы:
V
- Проверяемое значение (или переменная). Тип переменной или выражения должен быть приводим кbool
.MSG
- Дополнительные сообщения (можно задать любое количество: сообщения будут объединены в одно). В качестве сообщения может выступать строка или строковая переменная.
Сгенерирует ошибку, если V
равен false
.
Пример:
bool a = true, b = false;
TUPP_ASSERT_TRUE(a, "Exmaple message"); // Пройдёт успешно.
TUPP_ASSERT_TRUE(b); // Будет сгенерирована ошибка.
TUPP_ASSERT_FALSE(V, [MSG, [MSG, [...]]]);
Этот макрос позволяет проверить передаваемое булево значение на ложность. Имеет следующие аргументы:
V
- Проверяемое значение (или переменная). Тип переменной или выражения должен быть неявно приводим кbool
.MSG
- Дополнительные сообщения (можно задать любое количество: сообщения будут объединены в одно). В качестве сообщения может выступать строка или строковая переменная.
Сгенерирует ошибку, если V
равен true
.
Пример:
bool a = true, b = false;
TUPP_ASSERT_FALSE(b, "Exmaple message"); // Пройдёт успешно.
TUPP_ASSERT_FALSE(a); // Будет сгенерирована ошибка.
TUPP_MESSAGE(MSG);
Этот макрос позволяет вывести любое произвольное сообщение или строку в консоль. Имеет следующие аргументы:
MSG
- Выводимая строка или строковая переменная. Тип переменной должен быть неявно приводим кstd::string
.
Пример:
std::string msg = "Message 1";
TUPP_MESSAGE(msg);
TUPP_MESSAGE("Message 2");
TUPP_ASSERT_F(V_A, V_B, [MSG, [MSG, [...]]]);
Этот макрос позволяет проверить два значения значения с плавающей запятой на равенство с некоторой
точностью. На данный момент сравнение происходит только с точностью float
. Точность определена в
константе tupp::FLOAT_CHECKING_ACCURACY
. Имеет следующие аргументы:
V_A
,V_B
- Сравниваемые значения (или переменные). Тип переменных должен быть неявно приводим кfloat
.MSG
- Дополнительные сообщения (можно задать любое количество: сообщения будут объединены в одно). В качестве сообщения может выступать строка или строковая переменная.
Сгенерирует ошибку, если V_A
отличается от V_B
более, чем на tupp::FLOAT_CHECKING_ACCURACY
.
Пример:
float a = 5.0f, b = 5.0f, c = 6.0f;
float d = 5.0f + tupp::FLOAT_CHECKING_ACCURACY / 2.0f;
TUPP_ASSERT(a, b, "Exmaple message"); // Пройдёт успешно.
TUPP_ASSERT(a, c); // Будет сгенерирована ошибка.
TUPP_ASSERT(a, d); // Пройдёт успешно.
TUPP_ADD_TEST(TEST_NAME);
Регистрирует тест в библиотеке. Тест должен быть представлен функцией, имеющей сигнатуру следующую сигнатуру:
void (void)
Имеет следующие аргументы:
TEST_NAME
- Имя регистрируемой в качестве теста функции. Это имя также будет являться именем теста.
Пример:
void example_test()
{
// ...
}
int main(int argc, char* argv[])
{
TUPP_ADD_TEST(example_test);
// ...
}
int run(int argc, char* argv[]);
Метод для запуска тестов. Предполагается, что метод будет вызван после регистрации всех тестов
в функции int main(int argc, char* argv[])
в самом конце. В качестве аргументов метода будут
переданы аргументы argc
и argv
функции main
, а результат будет возвращён этой функцией.
Метод имеет следующие аргументы:
argv
,argc
- Массив строк - аргументов командной строки, и их количество.
Метод возвращает один из кодов возврата, описанных в разделе "Описание возвращаемых кодов ошибок".
Пример:
int main(int argc, char* argv[])
{
// Регистрация тестов.
return tupp::run(argc, argv);
}
void message(const std::string & msg, size_t line);
Метод для вывода сообщения в консоль. Используется в макросе TUPP_MESSAGE
. Аргументы:
msg
- Выводимое сообщение.line
- Потенциально: номер строки, где вызывается этот метод.
Вместо этого метода рекомендуется использовать макрос TUPP_MESSAGE
.
void add_test(const TestFunc & test_func, const std::string & name);
Регистрирует тест в библиотеке. Тест должен быть представлен функцией, или любым другим callable объектом имеющим сигнатуру следующую сигнатуру:
void (void)
Аргументы:
test_func
- Указатель на функцию или любой другой callable объект, представляющий тест.name
- Имя теста. Будет использоваться в выводе сообщений, а также в качестве значения ключа аргумента командной строки--test (-t)
.
Этот метод имеет смысл использовать, если имя функции не должно соответствовать имени теста, или в качестве теста используется какой-то callable объект.
Пример:
void example_test_func()
{
// ...
}
int main(int argc, char* argv[])
{
tupp::add_test(&example_test_func, "example_test");
// ...
}
void t_assert(bool v, const std::string & msg, size_t line, const TMsg & ... additionals)
Аргументы:
v
- Проверяемое значение. Ошибка сгенерируется, если значениеfalse
.msg
- Потенциально: сообщение, которое будет построено макросом на основании используемого выражения (вставляется в виде строки).line
- Потенциально: номер строки, где вызывается этот метод.additionals
- Дополнительные сообщения (можно задать любое количество: сообщения будут объединены в одно).
Метод, который используется макросами TUPP_ASSERT
и TUPP_N_ASSERT
. Не рекомендуется
использовать в чистом виде, но может быть полезен при добавлении специфичных assert
макросов.
void t_assert_tf(bool v, bool expected, const std::string & msg, size_t line,
const TMsg & ... additionals)
Аргументы:
v
- Проверяемое значение. Ошибка сгенерируется, если значение не равноexpected
.expected
- Ожидаемое значение.msg
- Потенциально: сообщение, которое будет построено макросом на основании используемого выражения (вставляется в виде строки).line
- Потенциально: номер строки, где вызывается этот метод.additionals
- Дополнительные сообщения (можно задать любое количество: сообщения будут объединены в одно).
Метод, который используется макросами TUPP_ASSERT_TRUE
и TUPP_ASSERT_FALSE
. Не рекомендуется
использовать в чистом виде, но может быть полезен при добавлении специфичных assert
макросов.
void t_assert_flt(float a, float b, const std::string & msg, size_t line,
const TMsg & ... additionals)
Аргументы:
a
,b
- Проверяемые на равенство значения. Ошибка сгенерируется, еслиa
отличается отb
больше, чем наtupp::FLOAT_CHECKING_ACCURACY
.msg
- Потенциально: сообщение, которое будет построено макросом на основании используемого выражения (вставляется в виде строки).line
- Потенциально: номер строки, где вызывается этот метод.additionals
- Дополнительные сообщения (можно задать любое количество: сообщения будут объединены в одно).
Метод, который используется макросом TUPP_ASSERT_F
. Не рекомендуется использовать в чистом виде,
но может быть полезен при добавлении специфичных assert макросов.
tupp::FLOAT_CHECKING_ACCURACY
- Константа с допустимой разницей между проверяемымиfloat
значениями макросаTUPP_ASSERT_F
и методаtupp::t_assert_flt
.tupp::TestFunc
- Описание сигнатуры функции, представляющей тест.
При активации этого режима (см. "Описание аргументов командной строки" ниже), если в тесте несколько assert'ов, один из которых вызывает ошибку, выполнение теста продолжится.
Пример:
void example_test()
{
TUPP_ASSERT_TRUE(false);
TUPP_MESSAGE("Выполнение продолжено");
}
В данном примере TUPP_ASSERT_TRUE(false)
вызывает ошибку. Если режим пропуска ошибочных ассертов
не активирован, то выполнение теста прекратится на этом макросе. Если же режим активен - выполнение
продолжится и в данном примере будет выдано сообщение "Выполнение продолжено".
TinyUnit++ предусматривает следующие типы сообщений:
- FAIL, SUCCESS - Результат прохождения теста.
- TEST_NAME - Имя теста.
- HEADER - Заголовок. Обособляется
####
. Информирует о начале и конце выполнения тестирования. - TEST_MESSAGE - Сообщения тестов. В этот тип попадают все сообщения, которые генерируют assert
функции и макросы, а также сообщения выводимые при помощи
TUPP_MESSAGE
. - REPORT - Отчёт. Выводится после прохождения всех тестов. Говорит, сколько тестов было запущено, сколько было пройдено успешно и т.д.
- DEFAULT - Сообщения, которые не подошли ни под один из выше перечисленных типов. Сейчас таких сообщений нет.
Тихий режим - это режим работы библиотеки с разным количеством выводимых сообщений от вывода всех сообщений до отсутствия вывода вообще.
Тихий режим имеет несколько настраиваемых уровней и опирается на систему типов сообщений, описанную выше. Уровень задаётся положительным числом. Некоторые значения уровней могут складываться, таким образом образуя уровень, который включает действие обоих складываемых уровней.
Уровни:
- 0 - Все сообщения выводятся.
- 1 - Скроет сообщения типа
TEST_MESSAGE
. - 2 - Скроет сообщения типа
TEST_MESSAGE
,TEST_NAME
,FAIL
иSUCCESS
. - 10 - Скроет сообщения типа
HEADER
. - 100 - Скроет сообщения типа
REPORT
. - 1000 - Скроет абсолютно все сообщения.
Правила сложения уровней:
- Уровни не могут складываться в пределах десятка. Т.е. нельзя сложить уровни 1 и 2, 10 и 20, но можно сложить уровни 1 и 10.
- Уровень 1000 ни с кем не складывается.
- --continue_after_assert (-a) - Активирует режим пропуска ашибочных assert'ов.
- --help (-h) - Вывод справки по аргументам командной строки.
- --silent_level (-s) [уровень] - Активация разных вариантов тихого режима.
- --test (-t) [имя теста] - Запуск теста с именем "имя теста". Этих ключей в командной строке
может быть несколько (для каждого имени теста отдельный ключ, т.е.:
-t test_a test_b
- неправильно,-t test_a -t test_b
- правильно). В таком случае запустятся все указанные тесты. - --version (-v) - Вывод версии и копирайта тест системы и другой информации.
- 0 - Тесты отработали успешно, каких-либо ошибок нет.
- 1 - По крайней мере один тест провален.
- 100 - Некорректная командная строка. В консоль будут выведены подробности по ошибке.
- 101 - Неизвестный ключ командной строки. В консоль будут выведены подробности по ошибке.
- 102 - Неверный контекст применения ключа. В консоль будут выведены подробности по ошибке.
- 200 - Неизвестная ошибка. При корректной работе такой ошибки появиться не должно.
- Цветной вывод и соответствующая настройка командной строки.
- Обработка C++ и системных исключений.
- Вывод списка добавленных тестов по аргументу командной строки.
- Warning'и и заглушки (для нереализованных тестов).
- Возможность замены
::
при вызове теста из командной строки. Нужно для тестов, которые были добавлены так:TUPP_ADD_TEST(some_namespace::test_function);
. - Вывод списка тестов в командную строку.
Версия состоит из трёх компонентов:
- Старшая версия - Глобальные изменения. Переход к версии 1 будет соответствовать реализации все задуманного и корректной работе имеющегося функционала. Также при переходе начиная с версии 1 предполагается, что не будет меняться формат ключей командной строки, сигнатуры функций и сигнатуры макросов в пределах всей старшей версии.
- Младшая версия - Значительные изменения, связанные с добавлением нового функционала, а также значительным (до версии 1.0.0) и незначительным (начиная с версии 1.0.0) изменением существующего. До версии 1.0.0 изменения младшей версии могут ломать обратную совместимость.
- Коррекция - Правка каких-либо ошибок. Не ломает обратную совместимость.