вторник, 26 февраля 2008 г.

Анти-паттерны модульного тестирования

Gojko Adzic в своем блоге процитировал неплохой набор анти-паттернов модульного тестирования. Существует мнение, что учиться нужно от положительного, т.е. например если вы учите кого-нибудь кататься на сноуборде, ему нужно показывать КАК НАДО кататься, а не как не надо. Но в то же время, если пока вы поднимаетесь на подъемнике, комментировать ошибки других спускающихся бордеров, это при определенном уровне понимания предмета может принести неплохой результат.

Собственно вот основные моменты, которые нужно избегать:

  • Disabling tests to make a build pass.
  • Это наверное самая распространенная ошибка - как только вы "выключили" тест, вы сделали шаг назад. Потому что потом наверняка не будет времени его исправить, чтобы включить обратно. И наверняка потом сломается еще один тест, а затем еще один.. Исправление сломанного теста должно быть задачей с наивысшем приоритетом. Если конечно вы заботитесь о качестве своего продукта.

  • Continuous integration not failing when unit tests fail.
  • Помните, в комнате XP команды обязательно стоит сервер автоматических сборок и соединенный с ним монитор, который показывает зеленый экран, если сборка прошла успешно, и красный, если были ошибки? Сломанные модульные тесты не должны давать экрану становиться зеленым, потому что если хотя бы один тест не сработал - сборка находится в нерабочем состоянии. А значит, ей нельзя пользоваться и ее нужно исправлять. Проверьте настройки своего сервера сборок.

  • (3rd party) API changes cause tests to fail.
  • Мое мнение - нужно быть безумцем, чтобы использовать сторонние библиотеки непосредственно в коде всего приложения, не инкапсулируя в свои классы. Это даже не относится к модульному тестированию, у вас поедет все приложение, если интерфейс компонента изменится даже незначительно.

  • Many tests fail when a single behaviour changes.
  • Здесь главное не забывать, что модульный тест предназначен для тестирования как правило одной функции кода - нужно стараться писать небольшие, максимально независимые тесты. Для тестирования набора функций существуют интеграционные тесты.

  • Data-sensitive tests.
  • Все наверное помнят, что по правилами тест должен быть независимым от хранилища данных. Но это правила, а в реальной жизни не всегда возможно писать такие тесты, потому что они будут стоить слишком дорого. Главное, минимально закладываться на набор данных хранилища. Нужно перед выполнением теста создавать тестовые данные, а не использовать уже готовые - потому что в противном случае велик риск поломки тестов и тесты не будут работать на серверах заказчика.

Важно всегда помнить, что нет никаких правил по написанию модульных тестов, есть только рекомендации. На то мы и делаем Agile.
"Кривой" или несоответствующий рекомендациям тест - всегда лучше, чем отсутствие теста.
Главное, чтобы он проверял ваш код и защищал вас от ошибок.

3 коммент.:

Фёдор комментирует...

В добавку: "запутанные" и "странные" тесты

Mikalai Kardash комментирует...

Хм... А как насчет:
(3rd Party Components) - а можно ведь просто написать тесты, проверяющие функционал 3rd party компонентов, да?

Data-sensitive tests Вообщето, таких правил нет. Все зависит от того, что тестировать. Тест конечно должен быть максимально изолирован, но не всегда такое получается, поэтому наверное и существует такие понятия как unit test, system (integration) test, automated (acceptance, ui) test.

ps: xunitpatterns.org

Дмитрий Лобасев комментирует...

(3rd Party Components) Можно написать тесты на функционал, но при изменении интерфейса компонента придется переписывать кучу кода, вместо того чтобы исправить один прокси класс, и тесты тут не помогут :)

ps. книжка супер, на ютубе даже видео выступления этого чувака на семинаре в гугле есть.