Минималистичный фреймворк модульных тестов для Си
Как-то на работе (а разрабатываем мы ни много ни мало — операционную систему) появилась необходимость писать модульные тесты к разрабатываемым функциям. В силу специфики разработки прикрутить какой-то внешний фреймворк не представлялось возможным. ОС все же вещь в себе, а без автоматизированного тестирования жизнь становится уж слишком непредсказуемой. В общем, пришлось написать свой юнит-тест-фреймворк.
Признаюсь сразу, идею слизал у MinUnit, но сам он мне показался неудобным. В результате получился один-единственный заголовочный файл:
#ifndef _UTEST_H_ #define _UTEST_H_ #include <stdio.h> #define UT_ASSERT_EX(expr,fmt,...) \ do { \ if (!(expr)) { printf("ASSERT: file \"%s\", line %d, function \"%s\": ",\ __FILE__, __LINE__, __FUNCTION__); \ printf(fmt, __VA_ARGS__); \ printf("\n"); \ return 1; } \ } while(0); #define UT_ASSERT(expr,msg) UT_ASSERT_EX(expr, "%s", msg) #define UT_TEST(test) \ do { \ printf("TEST: \"%s\" %s\n", #test, (_t_ ## test() ? "failed" : "OK")); \ } while(0); #define UT_TESTDEF(name, body) \ static int _t_ ## name () { \ do { \ body \ } while(0); \ return 0; } #endif /*_UTEST_H_*/
Использование, я полагаю, достаточно очевидно. Но на всякий случай пример:
#include "utest.h" int func1(int arg) { return arg*arg; } UT_TESTDEF(func1, int ret; ret = func1(5); UT_ASSERT(ret == 25, "blah-blah"); ret = func1(0); UT_ASSERT_EX(ret == 0, "ret is %d, must be 0", ret); ); int main() { UT_TEST(func1); return 0; }
Задачу свою такой подход вполне решает, так что невеликие размеры «фреймворка» пусть вас не смущают. Желающие могут навертеть вокруг этого свои рюшечки, а по мне и этого достаточно.

