Эффективные юнит тесты. Часть II
Aug 8, 2006 · CommentsПрограммированиеТестированиеЮнит тесты
Реализация алгоритма, описанного в первой части. В принципе исходный код говорит сам за себя. Остановлюсь на некоторых деталях.
Каждый элементарный тест описывается структурой:
struct Test
{
const char* name;
unsigned type;
unsigned mask;
bool positive;
bool (* tearUp)();
void (* tearDown)();
};
-
name – задает имя теста. Имя желательно выбирать коротким, поскольку полное имя комбинации тестов включает в себя имена всех элементарных тестов;
-
type - одна из констант TEST_XXX или их комбинация, определяющая тип теста. В примере тип каждого теста уникален. На самом деле это необязательное требование;
-
mask – комбинация констант TEST_XXX перечисляющая все типы тестов, совместимые в данным;
-
positive – ожидаемый результат теста;
-
tearUp – функция, выполняющая инициализацию и собственно тест;
-
teadDown – функция, ответственная за корректное завершение теста.
Константы TEST_XXX
представляют собой битовую маску, где каждому биту соответствует свой тип теста. В процессе выбора очередного теста список выбранных тестов сопоставляется с маской совместимых тестов:
if (
((mask & i->type) == 0) &&
((mask & ~(i->type | i->mask)) == 0))
{
Тест будет выбран только если тест еще не был выбран (первое условие), а также совместим с уже выбранными тестами. (второе условие).
В примере тесты группируются по категориям (или «вариантам»). Основной признак для такой группировки – в одну категорию попадают тесты, которые не могут входить ни в одну тестовую комбинацию одновременно.