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. Делитесь им в комментариях. Спасибо!

Похожие статьи:
Проєкт «Велопробіг за Україну» — це благодійна ініціатива, створена для підтримки України та українців в інформаційному просторі....
Меня зовут Максим, я работаю тестировщиком ПО, с интересом слежу за событиями в мире тестирования и IT. Самое полезное собираю...
15 серпня у Microsoft надали розробникам загальний доступ до прев’ю-версії своїх хмарних робочих станцій Microsoft Dev Box, пише The...
Тренинг, который мы вам предлагаем, является уникальной возможностью научиться разрабатывать программное...
Historically horseracing, in one form or another, has been around for thousands of years. Records exist from Ancient Egypt, Greece, Babylon, Syria, the Roman Empire and the list goes on. However, it...
Яндекс.Метрика