Сказка о неразобранных автотестах

Жил был проект, а в проекте делали продукт, а у продукта была веб-морда, и нужно было ту веб-морду тестировать, и были автотесты («Selenium» — подумал Штирлиц) для всех и всяческих сценариев. Автотесты регулярно запускали на свежих билдах, они достаточно быстро выполнялись и радовали всех «зелёными» результатами. «Красные» результаты быстро исследовали, чинили проблему, и каждый следующий запуск был «зеленее» предыдущего. Скоро сказка сказывается, да не скоро дело делается.

У меня есть друг, у которого есть друг, знакомый которого рассказывал про человека… На одном из местных TechTalk’ов зашла речь про автотесты, и выяснилось, что «в реальном мире это не работает». Тут нужен дисклеймер. Сам я на том техтолке не был, это мне коллега рассказал, как люди болью делились. Мол, продукты хорошие, автотесты тоже в целом есть, и запустить их не проблема. Проблема — разобрать результаты работы автотестов. Что выполнилось, что упало, где баг, где косяк автотеста — вот это всё. Не хотят люди результаты разбирать — неинтересно им как-то, что ли… И что с такими неразобранными результатами делать? Как заставить, нет «заставить» слово нехорошее, как мотивировать человека разобрать-таки результаты автотестов?

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

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

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

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

От результата

Нам ведь не нужны результаты автотестов. Нам нужно квалифицированное и обоснованное знание о состоянии продукта. Не хочешь возиться с автотестами, можешь не возиться. Главное — это самое знание предоставь. Как — дело десятое. Можешь «руками» всё пройти, можешь еще как-то. Лишь бы работало, было воспроизводимо и в разумные сроки. В общем, ты сам кузнец своей задачи.

От процесса

Ты за автотесты, но ведь нудятина же невозможная? Да, всё так, согласен. Но уйти от рутины совсем — не получалось никогда и ни у кого. Кроме Карлсона, но супергерои не в счёт. Рутина есть и будет, на каждом сколько-нибудь долгом проекте; это надо принять как неизбежность. Но можно варьировать количество рутины на каждую персональную душу населения.

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

Другой вариант — поделить весь большой сет автотестов на куски. Самые приоритетные выделить в отдельный пул и сперва выполнять только их, а остальные — пореже и только если Top-Priority тесты «зеленые» (вы слышали, он сказал «build verification test», он правда это сказал). Этих самых Top-Pri тестов не должно много получаться. Если какой-то из Top-Pri тестов, будучи «красным», не блочит 10% общей массы тестов, то может он и не Top-Pri.

Вообще, вариантов подобного перераспределения рутины можно придумать немало — лишь бы помогали работе.

Издержки: как за всяким процессом, кто-то должен за ним следить: что он работает, не провисает, не начинает мешать ходу проекта и так далее.

От инструмента

А может, всё проще и достаточно допилить инструменты, чтоб они помогали разбору результатов АТ (о, вот она, Важная Задача, которой я буду отмазываться в следующий раз).

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

Неказистый инструмент может серьёзно затруднить работу. Хороший и удобный инструмент не избавит от работы, но поможет её делать быстрее и качественней.

От проблем

Да нет, говоришь, это всё понятно, говоришь, но что толку, если половина падений тестов — это не баги продукта?

Автотесты не совершенны и пишутся людьми, а потому содержат свои ошибки и падают там, где не надо (и проходят где надо бы упасть, но не будем об этом). А железо и тестовое окружение — вообще не совершенны и настраиваются людьми, глючат и приводят к ложным падениям автотестов. Мыть в этом песке золото — баги продукта — та еще работёнка.

Ну что тут скажешь. Время исправлять грехи молодости: стабилизировать АТ, разбираться с настройками, учить роботов…

Или — придумать как получать всё-таки пользу от таких АТ.

От себя

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

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

 

Сказка ложь, да.

100500 конфигураций

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

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

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

Сомневаюсь, что можно как-то окончательно решить эту проблему пока продукт развивается; можно только попытаться уменьшить опасность и критичность пропущенных проблем (и – снизить вероятность их пропуска, да).

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

Начнем с относительно простой ситуации, когда заказчик и покупатель у нас один. Этот случай проще, так как мы можем довольно точно узнать, как [будет] настроена его система, и отбросить остальные варианты. Даже в этом случае возможны проблемы: не всегда удается в тестовой лабе воспроизвести масштаб и сложность боевой системы. Ок, давайте тестировать в «похожем окружении».

Вот тут важный вопрос – что такое это «похожее окружение»? Чем оно похоже на боевое, а чем отличается? Если ответ неизвестен – то и результат тестирования не вполне понятен. Зная ответ – уже можно понять, что мы можем адекватно проверить, а что нет, в каких местах могут потом появиться проблемы; можно подумать, как все-таки проверить эти проблемные точки (возможно – за пределами тестовой лабы).

Если покупателей много, то они обычно используют продукт по-разному – в разных условиях, с разными настройками. Чаще всего проверить все условия/настройки в срок невозможно, зато мы можем как-то расставить приоритеты. Более популярные конфигурации тестировать тщательней, менее используемые – поверхностно. Цель в том, чтоб избавить от проблем основную массу пользователей. Да, мы что-то можем упустить для редко используемого случая, но это заметят сравнительно немногие.

Опять важный момент: хорошо бы представлять, сколько их, тех немногих, и кто они; какие конфигурации популярны, а какие нет. Можно, конечно, пытаться угадать (не, не угадаете), лучше – как-то собирать эту информацию.

А что делать, если есть несколько примерно равнопопулярных вариантов? Тестировать все, конечно, но стараться как-то оптимизировать процесс. Несколько вариантов клиентской части? – настройте все и случайным образом используйте тот или другой для разных тестов. Автоматизируйте установку/настройку/тестирование системы и гоняйте важные тесты в разных конфигурациях. Перепроверьте, чем эти равнопопулярные варианты отличаются друг от друга, и сосредоточьтесь на тестировании отличающихся нюансов вместо прогона всех тестов на всех вариантах. В общем, есть о чем подумать, и чаще всего есть что придумать.

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

Если есть возможность – можно устроить какой-то вариант альфа/бета-тестирования. Договориться с крупным клиентом, что специфические особенности будут проверены в его тестовой лабе. Раздать продукт сотрудникам и спросить их мнение. Выложить бету в публичный доступ и собирать отзывы и баги.

Тут тоже, конечно, есть важный момент, и далеко не один. У крупного клиента могут случиться свои проблемы, и лабу он не предоставит. Или предоставит, но доступ туда будет такой заковыристый, что тестировать невозможно. Или пообещает сам протестировать, и не успеет вовремя дать фидбек. А в случае массовой беты – можно утонуть в непрофессиональных багрепортах, не разобраться в приоритетах найденных багов, пропустить «явно невероятную» проблему в релиз. В любом случае, запуская бету, подумайте, когда и какую обратную связь вы ожидаете, как вы собираетесь с нею работать, и как результат беты может повлиять на текущие планы по выпуску продукта.

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

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

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

4k+ знаков про тестовое окружение

Тестовое окружение – неизменный спутник тестирования. Неважно, какое ПО мы тестируем, без разницы, какую используем методологию: если мы выполняем тест, то, как минимум, нам нужен объект тестирования в подходящем состоянии. И как только этот объект появляется, появляется и оно, тестовое окружение.

Тестовое окружение (ТО) может готовиться заранее, а может «возникать» прямо в момент выполнения теста. Разным проектам нужны разные ТО, что естественно. ТО меняется вместе с развитием продукта, требованиями к нему, бюджетом и пониманием роли тестирования. Короче, как водится, идеального-вообще ТО не бывает, бывает – адекватное здесь-и-сейчас, решающее текущие задачи при данных обстоятельствах (ну и желательно с каким-то заделом на обозримое будущее).

Говорят, хороший интерфейс ПО – тот, который пользователь «не замечает», а просто решает свои задачи, работая с программой. Про ТО можно сказать что-то подобное: чем проще подготовка и выполнение тестов, воспроизведение дефектов, работа с прочими артефактами, тем лучше ТО. Чем меньше мы спотыкаемся о разложенные нами же грабли, не относящиеся к тестируемому продукту, тем больше мы спотыкаемся о грабли в продукте, разбросанные разработчиками. А этого от нас и ждут, ага.

Создание такого ТО, понятно, требует труда. По сути, это такой сопутствующий проект – со своими требованиями, дедлайнами и потребителями. Скорее всего, этот проект будет длиться не меньше, чем собственно разработка system under test (SUT). От этого проекта серьёзно зависит успех производимого продукта.

Можно выделить несколько требований, актуальных для большинства ТО.

Применимость

ТО должно отвечать поставленным задачам. Железо должно соответствовать требованиям к SUT. Хорошо бы, чтоб конфигурации были подобны тем, что используются в боевом режиме (или мы хотя бы знали diff).

Конечно, ТО должно позволять выполнить необходимые тесты и прочие активности. Должна быть возможность проверить различные важные конфигурации (поддерживаемые ОС, БД, локализации, и т.д.). В общем, тестировщики должны иметь возможность тестировать, иначе зачем всё?

Изолированность

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

Подобная изолированность защищает, с одной стороны, от особенностей конфигурации отдельных машин. С другой – от потери данных из-за нестабильности SUT. С третьей – упрощает контроль за состоянием SUT и конфигурациями, обеспечивает воспроизводимость тестов. Ладно, даёт шанс обеспечить воспроизводимость.

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

Доступность и простота

Если нет каких-то особых причин для обратного, ТО должно быть легко доступно для всех, кто с ним работает – тестировщиков, программистов, аналитиков и других интересующихся.

Не должно быть проблем с созданием нового экземпляра SUT в требуемой конфигурации.

Нам нужна возможность без особых затрат отслеживать состояние и использование ТО – что где находится и почему, кто использует тот или иной объект (например, копию SUT), где у нас есть свободные ресурсы, и т.д.

По возможности следует исключить конфликты использования общих ресурсов/объектов.

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

Управляемость

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

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

Стабильность

Пусть SUT сколь угодно нестабильна, ей можно, а ТО должно быть здоровым и непотопляемым. Тут стоит задействовать практики рекомендованные системным администраторам (кстати, невредно с ними проконсультироваться, если есть с кем) – мониторинг состояния железа, контроль нагрузки на сервера, регулярные бэкапы и подготовка сценариев на случай внезапной смерти Самого Важного Сервера…

В общем, все, что выглядит нужным и применимым.

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