Эффективные юнит тесты. Часть 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))
    {
Тест будет выбран только если тест еще не был выбран (первое условие), а также совместим с уже выбранными тестами. (второе условие).
В примере тесты группируются по категориям (или «вариантам»). Основной признак для такой группировки – в одну категорию попадают тесты, которые не могут входить ни в одну тестовую комбинацию одновременно.