Testing

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

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

Большинство из нас сочтут выпуск продукта, не прошедшего тестирование, безумной идеей, будь то производство самолетов, машин или велосипедов. Предполагается, что продукт должен пройти строгие процедуры тестирования перед поступлением в продажу. Компания же, выпускающая недоброкачественные товары, становится просто посмешищем. В связи с этим возникает вполне логичный вопрос: “А тестировала ли она свой продукт?”

А как обстоит дело с ПО? По каким-то причинам большинство считает вполне обычным делом создание ПО без процесса тестирования во время разработки.

Авось кто-нибудь, да и протестирует

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

Эта программа не работает!

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

Посмотрим, работает ли.

Что же здесь не так? Почему стоит переключиться на автоматизированное тестирование?

Будущее за автоматизированным тестированием

Уверен, что вам знакома такая ситуация. Вы написали функционал и начали проверять, работает ли приложение согласно ожиданиям. Выясняется, что нет. Что ж, нашли ошибку — исправили. Вновь запустили проверку, обнаружили уже другой баг и также его устранили. После череды подобных повторений у вас все заработало, и вы готовы предоставить код. Собравшись уже было отдохнуть, вы обнаруживаете, что ваш инструмент отчета об ошибках дал сбой. Оказывается, во время последнего цикла проверки вы пропустили один из этапов и не заметили еще один баг.

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

Другая проблема, связанная с ручным тестированием, — временные затраты. Чем больше у вас выполняемых действий для тестирования, тем больше времени оно занимает. В сложных системах ПО число возможных потоков действий, запускаемых в приложении, стремительно растет, и проверять их быстро вручную становится непрактично или просто невозможно. Вот почему вы прибегаете к тестированию только некоторых из них. Компьютеры, в отличие от людей, намного быстрее обрабатывают информацию, поэтому они решают и этот вопрос тоже, позволяя нам тестировать приложения с неимоверно быстрой скоростью. Первая попытка написать дополнительный код (автоматизированный тест) сразу же себя оправдает, так как тестирование выполняется перед каждым добавлением в ветку, развертывании или коммите.

Как?

Приступив к написанию автоматизированного кода, вы, возможно, столкнетесь с изобилием разнообразной терминологии и жаргона. По сути, автоматизированное тестирование ПО процесс простой — вы пишите программу для тестирования своей программы. Если ваша программа — калькулятор, выполняющий сложение, то вы пишите другую программу, отправляющую в него некоторые вводные данные. Например, мы отправляем цифры 2, 3 и проверяем, совпадает ли вывод калькулятора с нашими ожиданиями (5). В действительности мы пишем более сложные программы, чем простой калькулятор, но в большинстве случаев цель тестирования — определить, насколько ожидаемый вывод программы соответствует вводу.

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

Поддержание производительности тестов

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

В основании пирамиды располагаются низкоуровневые модульные тесты. Эти тесты предназначены для отдельных обособленных модулей (под модулем обычно подразумевается отдельный класс или путь). Продвигаясь вверх по пирамиде, тесты начинают включать всё большие части приложения (компоненты и модули). На высших уровнях располагаются тесты, которые загружают целое приложение и тестируют его согласно стратегии черного ящика. Чем выше уровень пирамиды, тем медленнее и нестабильнее тесты (что затрудняет их обслуживание). Вот почему форма пирамиды предпочтительнее конуса.

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

Первым делом тесты?

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

И лучше продумать тестовый код с точки зрения спецификации. Спецификации, как и сам тест, разрабатываются на интуитивном уровне и позволяют спрогнозировать поведение определенной части ПО. Если посмотреть на ситуацию с этой точки зрения, то написание тестов (спецификаций) перед написанием фактического кода звучит вполне разумно. В конце концов, как можно прописать приложение, если вы не определили, как оно должно себя вести?

Нужно ли это мне?

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

Перефразирую вопрос из вступительной части статьи. Подниметесь ли вы на борт самолета, чье ПО (определяющее то, как он полетит) не проходит тестирование?

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

Читайте также:


Перевод статьи Zvonimir Spajic: What we talk about when we talk about testing