13 марта 2011

Продолжаем писать тесты (Шаг 3.2)

И так, мы продолжили писать тесты. Если вы загляните в репозиторий, то заметите что в папке tests имеются тесты, возможно даже несколько. Они небольшие и вызвать их можно при помощи команды make test.

Для тех кто еще не выбрал репозиторий, сделайте следующее:

git clone git://github.com/Plambir/Tank-of-Destiny.git
cd Tank-of-Destiny/
cmake .
make test

Остальные могут сделать:

git pull origin master
cmake .
make test

Давайте рассмотрим три теста:

default_value.c
Это простой тест для разгона. Он должен проверить что после инициализации контекст будет содержать три переменные.
init.c
Этот текст проверить что ошибок не будет. Мелочь, а важно. Ведь тесты не только тестируют, но и отражают наши намерения в отношении поведения кода.
init_error
Самый интересный тест. Он проверяет, что если инициализация не пройдет, то будет выставлена ошибка в контексте.

Из init_error.c:

void
set_up()
{
  FILE *tmp;

  tmp = stderr;
  stderr = fopen("/dev/null", "w");

  game = init();

  fclose(stderr);

  stderr = tmp;
}

Зачем это? Это для того что бы не видеть сообщений об ошибках, которые будет генерировать функция init.

В остальном код идентичен init.c. Как это я так сделал?

Сначало, я сделал так:

add_custom_target(test
  COMMAND default_value
  COMMAND init
  COMMAND DISPLAY=error ${EXECUTABLE_OUTPUT_PATH}/init_error
  DEPENDS default_value init init_error)

Конечно еще все тесты линковались с библиотеками которые нужны для работы SDL, но не об этом сейчас. Так как же init_error вызывал ошибку в работе SDL?

Секрет в DISPLAY=error. Без корректно объявленной переменной окружения DISPLAY SDL_Init не сможет корректно инициализировать видео и вернет ошибку, которую мы и ждем в тесте. Вообще не очень хорошо так делать, просто так можно сделать.

Зависимость от окружения в тестах может принести вам много хлопот в дальнейшем, потому можно поступить иначе, избавив себя не только от зависимости от переменных окружения, но и от линкуемых библиотек.

Как это сделать? Если вы найдете комит в котором используется переменная DISPLAY и уберете в CMakeLists.txt все строки target_link_libraries, то увидите что компилятор не сможет найти определения ряда функций SDL.

Еще не догадались? Мы сами определим недостающие функции SDL.

У нас должно получиться четыре файла:

tests/src
|-- ...
|-- stub_sdl_get_error.c
|-- stub_sdl_init.c
|-- stub_sdl_init_error.c
`-- stub_sdl_quit.c

В них реализованы заглушки для используемых нами функций. Для теста успешной инициализации stub_sdl_init.c, для тесто на ошибку stub_sdl_init_error.c.

Рассмотреть их можно в репозитории. Там нет ничего сложно, просто пустые функции возвращающее нужные нам числа.

О тестах все. Точнее все о том как их можно писать. Разработка через тестирование продолжается. Следующим пунктом у нас на пути будет список отображений.