Архив за Сентябрь, 2012

Классификация видов автоматизированного функционального тестирования

Четверг, Сентябрь 6th, 2012

Пространная статья, в которой автор много философствует, но не претендует на истину в последней инстанции ввиду отсутствия репрезентативной статистической выборки.

На мой скромный взгляд (IMHO), безоглядное, чуть ли не повальное увлечение автоматизированным тестированием через GUI не слишком оправдано. Хотя сама по себе автоматизацию вполне имеет право на существование. “Потому что функциональное автоматизированное тестирования бывает разное” (с) Капитан Очевидность. “И в зависимости от ситуации оправдано применение того или иного” и снова спасибо Кэпу.

Можно предложить разные классификационные признаки. Ограничимся следующими: “кто пишет”, “когда пишет”, “кто выполняет”, “какой интерфейс использует тест”. Наиболее значимые различия:

  • “кто пишет.[программист | тестировщик]”;
  • “когда.[до кода(test first) | плюс-минус пара минут от кода (TDD) | после кода (регрессионное тестирование)]”;
  • “кто выполняет.[ программист |  тестировщик ]”;
  • “интерфейс[ GUI | API ]”.

Понятно, что вариантов больше. Тесты может кодировать и аналитик и более того, код тестов даже может быть частью спецификации требований, но это экзотика. Большинство людей работающих аналитиками вас просто не поймут. Хотя было дело, в одном из проектов я именно что сначала написал набор  автотестов, а потом программисты пытались написать программу. Ох и долго пытались… Я уж, и уволиться успел, а они все пытались. Но это действительно экзотика.

Так вот, IMHO, комбинация {пишет.тестировщик; когда.после кода; выполняет.тестировщик; интерфейс.GUI} самая бестолковая и одновременно безумно популярная.

Лирическое отступление. Почему эти тесты и наиболее бестолковые и наиболее популярные одновременно? Как один из вариантов объяснения: “Это позволяет тестлиду раздуть команду”. Действительно, пусть для того, чтобы продукт “N” стал хорошим, в нем нужно найти и исправить 2000 дефектов. И сделать это надо в течение года. При мануальном тестировании нормальная “цена” нахождения 1000 дефектов - это один человекогод. Значит нужно двое тестировщиков. С учетом неравномерности загрузки трое-четверо. А вот если ввести 100% автоматизацию посредством тесткомплита или там селениума, то понадобится уже 10-20 человек. Если же тестлид по настоящему талантлив, то при поиске следующей работы в его резюме будет красоваться гордая надпись: “Руководил отделом автоматизации тестирования в 50 человек”. Ну, понятно продавать себя надо уметь. Этому сейчас даже учат. Оно конечно можно налететь на грамотного рекрутера, который воскликнет: “Восхитительно! А позвольте полюбопытствовать, сколько дефектов за год нашли эти замечательно бравые полсотни человек?”

Но не будем искать злой умысел там, где достаточно простых объяснений. Причины могут быть и другие. Ведь на первый взгляд все выглядит просто замечательно. Мы покроем тестами всю функциональность и при выпуске новой версии эти тесты будут быстро находить дефекты. Прямо таки идиллия. А теперь откинемся на диван и немного подумаем. Думать тоже иногда надо. Говорят это помогает. С чего бы тесты будут находить ошибки? Наверное, потому, что изменилась функциональность (спасибо Кэпу). Но если изменилась функциональность, то наверное нужно на конкретно эту функциональность поменять тесты? Логично. Смотрите, что получается:

  1. Софт ушел на тестирование, а тестировщики вместо того, чтобы предоставить информацию о дефектах начинают лихорадочно править тесты. Учитывая, что написание кода тестов сравнимо с написанием собственно кода, софт проведет в очереди довольно много времени. Это потери. Это ухудшение потока.
  2. Когда ошибки таки будут найдены программист будет полностью вне контекста и потратит прилично времени на переключение.

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

Т.е. перед тем как внедрять  {пишет.тестировщик; когда.после кода; выполняет.тестировщик; интерфейс.GUI} внедрите {пишет.тестировщик; когда.до кода; выполняет.программист; интерфейс.GUI}. Такой подход действительно по настоящему эффективен. Из третьих рук я слышал, что по настоящему эффективная фирма (годовой проход в расчете на сотрудника порядка $1 000 000) придерживается именно этого подхода. Конечно, чтобы перейти к такому методу нужно серьезно поднять культуру разработки, что уже само по себе сильно помогает (спасибо Кэп). Придется внедрить стандарт именования локаторов, что дополнительно сделает тесты нехрупкими (Кэп?! но как вы догадались?!). Придется ввести процедуру проектирования пользовательского интерфейса, что дополнительно сильно улучшит качество ПО. Вообще такой подход прямо таки вынуждает “мыть руки перед кодированием”. Если начать с него, то потом можно и о регрессионном тестировании подумать. База тестов-то в любом случае останется.

Прочие варианты с GUI в качестве интерфейса не слишком интересны. Наверное, можно представить себе “полуторное” программирование, при котором два программиста за одним ПК пишут интерфейс пользователя, а потом один идет писать реализацию, а другой тесты, но как то в это верится с трудом.
Комбинация {пишет.программист; когда.плюс-минус пара минут от кода; выполняет.программист; интерфейс.API} популярна, скорее, в коллективах кросфункциональщиков, где нет выделенной роли тестировщиков. Там, же где роль тестировщиков выделена, программисты пытаются от написания автоматизированных тестов уйти. Впрочем, и там где тестировщиков нет, там тоже часто эта практика часто умирает. Я полагаю, что это связано с одной из форм прокрастинации:

Посылка 1. Кодер лучше умеет писать код, нежели проектировать тестовые наборы.

Посылка 2. Человек склонен откладывать “на потом” (на практике “навсегда”) то, что он умеет не слишком хорошо.

Вывод. Кодеры будут стараться отказаться от практики юнит тестирования.

А уж причин для отказа можно придумать массу. Пойдет и такая: “написание кода тестов занимает примерно столько же времени, сколько и написание кода”. Люди умеющие логически мыслить легко отклоняют эту причину. Ведь то что, написание юнит тестов заняло 100 часов и написание кода заняло 100 часов вовсе не означает, что стало 200 вместо 100. А вот то, что стало 200 часов вместо первоначальных 300 без юнит тестов - это вполне вероятно.

Но. Но можно предположить, что без предварительного обучения кодеров тестдизайну внедрение практики юнит тестирования будет не слишком эффективным. Вот над этим действительно стоит задуматься.

Прежде чем двинуться дальше стоит сказать вот о чем. Капитан О: “API оно разное бывает”. Под юнит тестированием часто подразумевают тестирование отдельных классов и функций. Но гораздо интереснее, когда речь идет об интерфейсе предоставляемым сервисом и/или компонентом. Будет это SOAP, или обмен по ftp, или еще что-то не слишком важно. Чем большим оказывается число компонент и/или сервисов использующих один и тот же интерфейс, тем выгоднее становятся тесты {пишет.???; когда.до кода; выполняет.не важно; интерфейс.API}. Сначала спроектировать и описать протокол, потом тесты и только потом код. Так делать выгодно. Более того иногда это чуть ли не единственный способ сдать проект. Но об этом явно в другой статье.

PS. Я рассмотрел только интересные с моей точки зрения виды тестов. Классификацию можно расширить и рассмотреть еще какие-то виды. Но потом.

PSS. Я убежден, что найдется множество людей, которые выступят в защиту тестов вида: “{пишет.тестировщик; когда.после кода; выполняет.тестировщик; интерфейс.GUI}”. Вероятно они будут приводить казуистические доводы типа: “Эти тесты не для того, чтобы находить ошибки, а для того чтобы предотвратить их попадание в продакшен”. Мой ответ: “сами поняли чего сказали? Не поняли, так идите перечитайте.” И встречный ответ. Производительность таких автотестов считается очень простым способом - это число дефектов найденных при прогоне этих тестов деленное на число человеколет вложенных в разработку и поддержку этих тестов. Какая у вас производительность? 20 дефектов на выброшенный год? Свободны. Это смешно.