Exploratory Testing: три истории применения тест-дизайна

Меня зовут Алексей Чаплиц. Имея за плечами более 20 лет опыта вне IT-индустрии, я стал тестировщиком ПО три года тому назад. Больше о том, как и почему я стал Software Tester, можно узнать из моего интервью ведущим подкаста QAGuild.

Это статья — моя первая проба пера в сфере тестирования, в частности на тему Exploratory Testing. Моя главная мотивация — поделиться небольшим опытом и ноу-хау с теми, кому это может пригодиться.

Под термином Exploratory Testing я понимаю не столько «свободный» стиль ручного тестирования, сколько осмысленное и систематическое, хотя и творческое, исследование причинно-следственных связей. Цель такого тестирования — оптимизация работы тестировщика, а его итог — отсутствие дорогостоящего устранения багов на продакш-уровне и наличие качественного продукта.

В статье читатель найдет три истории. В каждой описаны по одному методу тест-дизайна, которые я, зная того или нет, применял. Их анализ сделан задним числом (постмортем). Больше об этих методах можно узнать в книге «Explore It!» Элизабет Хендриксон.

История первая: как C.R.U.D. помог мне проверить GUI

Пару лет назад я присоединился к небольшой, но распределенной команде разработки, которая состояла из пяти человек — Requirements Engineer/PO/UX Designer (в одном лице), двух разработчиков и двух заказчиков-инженеров из отдела R&D.

Я получил задачу тестирования ПО для работы с файлами XML-формата для управления программируемых станков для высокоточной лазерной резки металла.

Контекст тестирования

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

Использованная техника тест-дизайна

Книга «Explore It!» описывает простую, но эффективную пошаговую технику тест-дизайна — C.R.U.D. (Create, Read, Update, Delete). Обычно она применяется для проверки различных элементов в реляционных базах данных со структурой parent-child. Я применил этот подход для тестирования GUI вышеупомянутых станков, в которых использовались файлы с такой же структурой.

XML-файл с множеством параметров для управления станком

Шаг 1: Create (создание файлов)

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

Однако для создания негативных тестов я редактировал тестовый файл, заменяя параметры нужного типа на неприемлемые, например, int вместо double. Таким образом создавал «новые» файлы.

Диалог с сообщением об ошибке после введения параметра недопустимого типа

Шаг 2: Read (чтение файлов)

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

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

Диалог с сообщением об ошибке при открытии испорченного файла

Шаг 3: Update (обновление файлов)

Программа позволяла обновлять данные в файлах — как внутри программы, так и снаружи. При этом она должна была оповестить об изменениях в соответствующем диалоговом окне с возможностью сохранить их. Для проверки этого функционала я либо вносил изменения в параметры в UI или в текстовом редакторе в то время, как этот файл был открыт в программе, затем закрывал его.

Шаг 4: Delete (удаление файлов)

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

Тестовая сборка в TestRail для проверки функционала предупреждения об отсутствии запрошенных файлов

Результат анализа поведения тест-объекта

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

Несколько тщательно выписанных пользовательских историй для стартовой страницы приложения

Что можно было изменить

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

Вывод

C.R.U.D. (Create, Read, Update, Delete) — простой и эффективный метод тест-дизайна. Я рекомендую его к применению по назначению, то есть в реляционных базах данных, или в аналогичных кейсах. Если вы знаете о противопоказаниях для использования метода, пишите в комментариях к статье.

История вторая: как я определял покрытие тестами больших рисков

На новом проекте (речь о нем пойдет подробнее в третьей истории), куда я пришел на замену выбывшего тестировщика, было три уровня тестирования, с тремя командами и тестовыми кампаниями. Я стал членом третьей команды, которая занималась регрессионным и smoke-тестированием еженедельных релизов и их хотфиксов.

Контекст тестирования

В проекте уже существовали тестовые кампании для наших целей. И хотя они покрывали основной функционал, из их содержания и описания нельзя было понять, покрывали ли они большие риски. Для того чтобы убедиться в этом, я применил технику тест-дизайна из книги «Explore It!».

Использованная техника тест-дизайна

Книга предлагает следующие три шага:

  • Составить список стейкхолдеров «в теме» (ПМ, ТМ и другие) для сбора информации.
  • Узнать у них о текущих жалобах и будущих страхах, связанных с продуктом.
  • Проверить базу данных (например, в Jira или в Вики проекта) с описанием критических багов и их кластеров.
  • Протестировать с помощью известных техник с граничными переменными, вариациями данных, состояний и т. п.

Этот подход имеет элементы классического управления рисками проекта и продукта, а его успех зависит от качественного анализа (см. первые три шага). Как оказалось, именно он стал моим главным фокусом.

Шаг 1: Составить список стейкхолдеров «в теме»

Вот как выглядел мой список:

  • Release/Test Manager;
  • Incident Manager/руководитель службы поддержки;
  • модератор пользовательского форума;
  • Product Manager;
  • разработчик приложения.

Шаг 2: Узнать у стейкхолдеров о текущих жалобах и будущих страхах, связанных с продуктом

Вот такие вопросы я задал каждому из стейкхолдеров:

  • Release/Test Manager: существует ли анализ взаимосвязей между элементами архитектуры приложения с точки зрения рисков? Анализ явных и неявных ожиданий пользователей? Области для улучшения и их приоритизация? (см. фото с примером анализа House of Quality).
  • Incident Manager/руководитель службы поддержки: какие самые «горячие» проблемы пришлось решать за последний месяц? Результаты их причинно-следственного анализа?
  • Модератор пользовательского форума: что обсуждают больше всего на форуме (от 200 уникальных посещений темы)?
  • Product Manager: какой функционал используется более всего? Какой приносит больше дохода (например, предоплата услуг)?
  • Разработчик приложения: существует ли список с кодом ошибок, чтобы найти риски, еще не покрытые тестами?

Пример анализа House of Quality

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

«Радар» рисков

Шаг 3: Проверить базу данных с описанием критических багов и их кластеров

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

Шаг 4: Протестировать с помощью известных техник с граничными переменными, вариациями данных, состояний и т. п.

Этот шаг я не применял (см. результат анализа ниже).

Результат анализа поведения тест-объекта

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

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

«Ты сделал двойную работу!» — скажет читатель. Согласен. Однако я смог убедиться в том, что большие риски были покрыты сборками. До этого момента, это было не очевидно на моем уровне тестирования.

Что можно было изменить

Я поделился своим подходом к тестированию на основе рисков и его первым результатом с коллегами и тест-менеджером. Однако это не вызвало у них какого-либо отклика. У них не было ни желания, ни времени отвлечься на изучение и применение нового метода тест-дизайна. Думаю, что это не помешало бы тогда.

Применив подобный подход, можно было бы:

  • Отточить этот метод после итеративного использования, обсудив его первое применение.
  • Проводить сессии оценки рисков по методу, описанному выше (или любому другому), с регулярностью раз в два-три месяца.

Вывод

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

История третья: как я «ловил» невоспроизводимый баг

Мое задание на этом проекте было непростым. Оно состояло в том, чтобы автоматизировать с помощью специального инструмента сценарии ручных тестов для Streaming Media Box (далее SMB). SMB — это приставка мультимедийных потоков, которую мой тогдашний работодатель — телекоммуникационная фирма — активно поставлял десяткам тысяч своих клиентов (см. фото).

Streaming Media Box (приставка мультимедийных потоков) с ПУ

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

Контекст тестирования

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

Скриншот экрана ТВ с пользовательскими профилями с разными именами

Создание профиля состояло из четырех этапов:

  • Создание профиля с помощью программы на SMB.
  • Верификация через SSO (Single Sign-On — одноразовую регистрацию) для сохранения на главном сервере.
  • Передача параметров созданного профиля с главного профиля через прокси-сервер на SMB. В то же время, создание профиля с любым другим именем было всегда возможно.
  • Появление созданного профиля в UI на SMB. На фото представлен скриншот экрана ТВ с пользовательскими профилями с разными именами.

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

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

Пошаговое решение проблемы

Книга «Explore It!» предлагает «поймать» невоспроизводимый баг в четыре шага:

  • Собрать доказательства, и на их основании найти закономерности появления бага.
  • Провести мозговой штурм факторов, которые окружают или усугубляют проблему.
  • Использовать модель состояний (state models) для фиксации времени появления проблемы.
  • Провести предметное обсуждение проблемы с экспертами, которых она затрагивает.

В своем анализе (уже задним числом) я использовал шаги 1, 2 и 4.

Шаг 1: Собрать доказательства, и на их основании найти закономерности появления бага

  • Когда появился баг? — Он появлялся сразу после того, как создавался профиль с тем же именем на другом SMB, и вся тестовая сборка запускалась повторно.
  • Какова была связь между тестовыми объектами при появлении бага? — Как только на двух SMB был создан профиль с одним и тем же именем, повторное создание нового профиля с тем же именем на первом SMB было невозможно, а вся тестовая сборка падала.
  • Просматривается ли здесь некая закономерность? — Было очевидно, что профиль на втором SMB как-то мешал повторному созданию профиля с тем же именем на первом SMB. А с любым другим именем было всегда возможно.

Шаг 2: Провести мозговой штурм факторов, которые окружают проблему

1. Что говорят другие тестировщики? Первая идея: таймауты (периоды ожидания) перед исполнением автокоманд в скриптах недостаточны. Однако они были вполне достаточны для ожидания ответа от бэкенда.

Вторая идея: скрипт автотеста исполняет команду «Нажать ОК» множество раз в то время, пока клиент регистрируется через SSO на главные сервер. Но, как показала проверка, многократное нажатие кнопки ОК не останавливало создание профиля с любым другим именем.

Третья идея: профиль с тем же именем уже существует на одном из нескольких SMB после первого удачного запуска тестовой сборки. Это уже было известно и подтверждало некую закономерность.

2. Что говорят инженеры, ответственные за бэкенд? Первая идея: аккаунт созданного профиля имеет скрытые детские профили, оставленные после ранних тестов, которые не отображаются в UI SMB. Проверка и удаление таких профилей в кабинете пользователя, однако, не решило проблемы.

Вторая идея: однажды созданный профиль никогда не удалялся с главного сервера. Проверка подтвердила этот факт и указала на ранее описанную закономерность.

Шаг 3: Использовать модель состояний (state models) для фиксации времени появления проблемы

Этот этап не применялся полноценно в анализе. Время появления бага было обнаружено на первом этапе анализа (см. п.1 выше).

Шаг 4: Провести предметное обсуждение проблемы с экспертами, которых затрагивает проблема

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

После обсуждения с сисадмином из Голландии я поднял снова проблемный вопрос перед руководством. В итоге этот администратор снова открыл обсуждение вопроса в уже существующем тикете в Jira. В конце концов, он удалил у себя на сервере профиль с тем же именем, который был создан на другом SMB и — о, чудо! — проблема падающей сборки решилась сразу. Теперь им надо было работать над тем, чтобы этот профиль удалялся всегда.

Результат анализа поведения тест-объекта и взаимодействия участников

  • Следующая закономерность поведения тестовых объектов четко прослеживалась: создание профилей с одним и тем же именем на двух SMB заставляло сборку падать.
  • Программа не предусматривала появление диалога с предупреждением о том, что создание одноименного профиля на другом SMB нежелательно.
  • Тестировщики не создали тестовую сборку, которая бы целенаправленно тестировала взаимосвязь SMB — SSO — прокси-сервер — главный сервер. (Показать пример конкретной системы я не могу из-за NDA, но думаю, что что-то подобное можно найти в сети.)
  • Простое решение проблемы заняло много времени и сил. Это я могу отнести только к человеческому фактору.
  • Взаимосвязанные тесты склонны иметь проблемы, которые тяжело вычислить.

Что можно было изменить

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

Во-вторых, по возможности избегать создания сборок из взаимосвязанных тестов, которые имеют «встроенный» потенциал проблем.

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

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

Вывод

Индуктивный метод (от деталей — к закономерностям) анализа проблемы невоспроизводимого бага, предложенный в книге «Explore It!», помог, пусть и постмортем, проследить разрешение проблемы падающей тестовой связки. Его этапы могут служить схемой решения подобных проблем.


Буду рад узнать о вашем опыте в Exploratory Testing. Делитесь им в комментариях. Спасибо!

Похожие статьи:
Организатор: SmartMe UniversityТренер: Кучеренко Андрей Мастер-класс по разработке через тестирование поможет разработчикам эффективно...
[Про автора: Альона Черненко-Диба — QA Manager у Astound Commerce з 11-річним досвідом в ІТ — від джуніор тестувальника до функціонального...
Компания Lenovo представила два новых ПК под управлением операционной системы Windows 10: Lenovo YOGA 900 и YOGA Home 900. Легкие и мобильные, они, по...
В выпуске: чего ждать в 2019, безопасность internal сервисов, Cortex в CNCF, 82% компаний уже немного с DevOps, почему Kubernetes крут, и он вам...
Комітет Верховної Ради України з питань податкової та митної політики рекомендував парламенту ухвалити законопроєкт...
Яндекс.Метрика