Блеск и нищета автоматизации тестирования — репост

Намедни на хабре появилась интересная статья, которую мы, в силу нашей профессиональной специфики, не можем не предложить к прочтению дорогим читателям. От себя хочется заметить, что полная автоматизация процесса тестирования — это «недостижимый идеал». К нему все стремятся, но, как ни крути, ручное тестирование никуда не денется. Небольшой комментарий от наших специалистов — в конце материала. Также мы взяли на себя смелость проиллюстрировать текст скриншотами из нашей тестовой лаборатории.

Принято считать, что наличие автоматических тестов — это безусловное благо. Если разработчики пишут тесты — это хорошо, чем больше тестов, тем лучше. При этом, в реальности их чаще не пишут, а все тестирование делают вручную.

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

Пример теста для проверки одной из особенности карт в игре Берсерк: Катаклизм
Пример теста для проверки одной из особенности карт в игре Берсерк: Катаклизм

Преимущества автоматических тестов

Автоматизированное тестирование имеет ряд существенных преимуществ по сравнению с ручным тестированием.

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

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

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

Точность — автоматические тесты проверяют ровно то, что описано в сценарии, во всех деталях и мелочах. Они не отвлекаются, не путают и не забывают.

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

Преимущества ручного тестирования

Ручное тестирование, тем не менее, превосходит автоматизированное по многим аспектам.

Проворность — проверить что-то вручную в первый раз легко и быстро. Автоматический тест нужно прежде разработать. Практически всегда это гораздо медленнее ручной проверки.

Гибкость — ручное тестирование можно проводить гораздо разнообразнее, и изменение способа тестирования практически ничего не стоит. Давайте протестируем в Safari — пожалуйста, на Chromebook — нет проблем, IE6 — придется запустить виртуальную машину, но тоже можно.

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

Небольшой тест проверки заголовкой на одной из страниц сайта цикла "Ириска" от Вадима Панова
Небольшой тест проверки заголовков на одной из страниц сайта цикла «Ириска» от Вадима Панова

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

Осмысленность — хотя каждая вещь в отдельности может быть абсолютно корректна, люди гораздо легче понимают, что вместе эти вещи не имеют никакого смысла.

Выразительность — мало найти проблему на уровне «ничего не работает!», важно правильно объяснить, в чем она заключается и уметь ответить на дополнительные вопросы разработчика. И в этом люди также лучше автоматических тестов.

Аутентичность — большинство приложений мы пишем для людей, и именно поэтому люди лучше всего подходят для их тестирования.

Блеск парадоксов тестирования

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

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

Потратив на тестирование 1 день, мы добьемся 90% довольных пользователей. Тестируя неделю — 99%, тестируя месяц 99.5%. На достижение все меньшего и меньшего результата мы тратим все больше времени. Это нецелесообразно.

Исправляя проблемы быстро, можно добиться гораздо более высокого качества продукта, нежели вкладывая все имеющиеся ресурсы в достижение полного покрытия тестами. Соль в том чтобы найти баланс в приложении сил.

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

Автоматическое тестирование дает очень маленькую отдачу на коротких дистанциях. В каждый отдельный момент, решая что выгоднее, писать тесты или не писать, второе всегда предпочтительнее.

Ситуация в корне меняется в длительной перспективе. Код приложения необходимо рефакторить, чтобы он не умер. Когда программисты все переделали — тестировщики должны все проверить. Полный цикл регрессионных тестов. Неделя? Две? Месяц? Или еще хуже: программисты обновили версию ключевой библиотеки. День работы, вроде все компилируется — отлично! И все равно тестировщики должны проверить все. Безумие. Пройдя через такое несколько раз, любой будет готов пойти на что угодно, лишь бы избежать подобных ситуаций в будущем. Для обеспечения стабильного базового уровня качества необходимо вкладываться в автоматизацию тестирования.

К сожалению, автоматические тесты не всегда являются решением, иногда они сами становятся проблемой.

Нищета автоматизации тестирования

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

Решение: написать автоматические тесты, которые все это делают.

Но не все так просто.

Написание тестов — это разработка, точно такая же, как и разработка основной бизнес-логики. Она требует ресурсов и квалификации. Обеспечивая качественное покрытие кода приложения тестами мы одновременно замедляем разработку как таковую. И замедляем не на 10%, а вдвое, втрое или даже больше.

Скорость — понятие относительное. Каждый конкретный тест, конечно, выполняется очень быстро, особенно чистые unit-тесты, когда все проверки происходят локально. Интеграционные тесты, REST-тесты тоже сравнительно быстрые. Что такое 100 миллисекунд, ну пусть даже 1 секунда, даже десятки секунд для selenium тестов — ерунда по сравнению с ручным тестированием. Но когда количество тестов хоть сколько-нибудь существенно, быстрые тесты оказываются очень даже медленными. Прогон тестов за 5 минут? Полчаса? Три часа? Два дня? Еще даже не добившись полноценного покрытия бизнес-логики, всерьез встает вопрос о том как запускать не все тесты, или запускать тесты не каждый раз — иначе уже автоматические тесты начинают тормозить разработку.

Примечание: Тесты можно существенно ускорить, вложившись в железо — выделить под них отдельный сервер, 10 серверов, 50 и т. д. Некоторые компании могут позволить себе и 1000 тестовых серверов, но далеко не все.

Тест в Eclipse Java Neon, который использует selenium web driver
Тест в Eclipse Java Neon, который использует selenium web driver

Инструментарий плох. Ни одна из мейнстримных платформ программирования не проектировалась с целью обеспечить возможность максимально просто и полноценно разрабатывать тесты. В Java все тестовые фреймворки являются сторонними библиотеками. Запуск тестов, осуществление проверок, создание mock-объектов — все это есть, но по частям и вне платформы. В Go тестовый фреймворк уже добавили в экосистему языка изначально, но это только запуск тестов. Выбор подходящего инструментария для написания тестов это отдельная проблема, требующая решения.

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

Блокируют изменения. По своей природе тесты призваны проверять, что ничего не изменилось. Если что-то начало работать не так — это баг. Но когда бизнес-логика меняется, даже если изменение корректно и полностью соответствует новым требованиям — тесты об этом ничего не знают. Изменений нескольких правил может привести к необходимости исправить десятки, если не сотни тестов, особенно если покрытие действительно хорошее.

Ограничивают рефакторинг. Тесты тоже нужно рефакторить, даже если бизнес-логика не меняется, и в коде происходят лишь косметические изменения. Это может привести к тому что нужно поправить 5 мест в основном коде и еще 80 в тестах. Каждый в такой ситуации задумается: а стоит ли делать что-то большее, чем переименование метода.

Сизифов труд — вот во что превращается разработка через тестирование, когда тесты пишутся до написания кода или хотя бы по ходу дела. Любой грамотный разработчик рефакторит код в процессе его написания по мере того, как он все глубже разбирается в проблеме и понимает, как реализовать решение лучшим образом. Но если он пишет тесты одновременно с кодом, кроме изменений в коде ему приходится менять еще и тесты. А в отличии от рефакторинга готового кода, рефакторинг кода в работе обычно гораздо масштабнее, значит и требуемые изменения в тестах будут соответствующими. И так — много раз еще до того, как код уйдет на ревью. Половину рабочего времени в мусор — легко.

Количество тестов обманчиво: 3000 тестов в сумме — на веб-интерфейс, REST API, бизнес-логику и юнит-тесты — могут проверять с натяжкой 1000 ситуаций. Все остальное — дублирование.

Автоматическая регрессия не отменяет ручную вопреки главной задумке. Все потому что автоматические тесты проверяют много чего, но далеко не все. Но что конкретно они проверяют, а что нет — никто не знает. Нам нужно проверить регистрацию. А еще у нас есть 18 927 тестов. Если какой-то из них красный — «все хорошо», можно вернуть задачу к разработчикам — пусть разбираются. Если все тесты зеленые — это ничего не значит до тех пор, пока человек, отвечающий за ручное тестирование, не будет уверен, что из логики регистрации проверяется автоматически, а что все еще нужно проверить вручную. А тестов почти двадцать тысяч — в этом невозможно разобраться. Результат — проверить вручную нужно все.
img-2017-02-09-113245Неудивительно что некоторые уходят из разработки продавать пластиковые окна, обучать бильярду или варить кофе (и это все реальные случаи).

Текст: Дмитрий Мамонов 

 

Самое в этом вопросе сложное — определение баланса между ручным и автоматизированным тестированием. Нельзя отказываться от одного в пользу другого. При всей привлекательности автоматизированного тестирования, оно имеет ряд существенных недостатков и проблем. В то же время, ручное тестирование оптимально не всегда. Самый простой способ выбрать вид тестирования — просчитать время, которое на него уходит (от написания кейсов, написания самих тестов, прохождения, создания отчетов и прочее) и сравнить. Для маленьких сайтов-визиток автоматизированное тестирование покроет все нужды и сэкономит огромное количество времени, сил и денег. Для активно развивающихся проектов только ручное тестирование поможет вести разработку в правильном темпе. В таких проектах приступать к автоматизации тестирования нужно только после «фиксирования» блока/элемента/фичи. Если у вас форма логина не меняется на протяжении полугода, то автотест справится с её проверкой лучше любого «ручного» тестировщика.