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