Что пишут в блогах

Подписаться

Онлайн-тренинги

Что пишут в блогах (EN)

Разделы портала

Про инструменты

.
Управление тестами в TestOps: храните информацию, а не выводы
24.06.2021 00:00

Автор: Руслан Ахметзянов, Qameta Software

Обеспечить представление данных из любой большой системы так, чтобы человек мог спокойно с этими данными работать — задача нетривиальная, но давно решенная. В этой гонке уже давно победило "дерево". Папочные структуры в операционных системах знакомы всем и каждому и исторически простое дерево в UI/UX становится первым решением для упорядочивания и хранения данных. Сегодня поговорим о тестировании, так что в нашем случае объектами хранения будут выступать тест-кейсы. Как их хранят чаще всего? Верно, в папочках!

Привычно? Да. Но так ли это решение хорошо и универсально? Вопрос подкрепляется существованием исключений: почта, JIRA-тикеты и много чего другого хранится не в папках. Давайте разбираться, почему.

Единое дерево

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

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

Что с ним не так?

Представим, что у нас есть замечательный веб-сервис, тесты на него написаны, разложены по папкам (по одной на каждую страницу) и выполняются раз в неделю, все счастливы. Однако, в какой-то момент к руководителю QA приходит менеджер (а они всегда приходят!) и просит рассказать о покрытии тестами микросервисов. Это не то, чтобы большая проблема — просто теперь в дополнение к существующей структуре нужно как-то собрать информацию о тестах из папочек и соотнести ее с микросервисами и сделать соответствующий (новый) отчет. Впрочем, чтобы в следующий раз не заниматься рутиной, старший тестировщик предлагает ввести фиксированные уровни у дерева: так у нас появится возможность иметь данные по командам в нашей структуре данных, а команды намного быстрее будут со своими репозиториями разбираться! Отличное решение, только в следующий раз менеджер просит статистику покрытия по фичам (еще один новый отчет)... Если тестов много, сотни или тысячи, то создание каждого нового среза потребует погружения внутрь всех вложенных ветвей и перераспределения тест-кейсов по новой структуре для анализа.

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

Минусы дерева папок — отсутствие гибкости в доступе к данным и аналитике и сложность рефакторинга в условиях, когда требования к тестированию меняются.

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

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

В итоге папочки станут снова управляемыми, уровни вложенности структурируются, но снова получится только один срез — по фичам. Если попытаться создать структуру с двумя срезами, по фичам и компонентам сразу, ее сложность и запутанность создаст больше проблем, чем пользы. А если у вас 3000 тест-кейсов? А если 10000?

Впрочем, чтобы столкнуться с ограничениями папочной структуры хранения тестов, не обязательно ждать менеджера с каким-либо "хитрым" запросом. Если в недавно переработанной структуре по фичам понадобится найти самый "красный" компонент, сделать этого скорее всего не получится: вы найдете самую красную "папочку" с фичей, но какие компоненты в ней тестируются, сходу будет не понять. С любой метрикой качества тестирования или продукта придется идти разбираться головой и руками.

Еще один подводный камень хранения тестов в папках ждет тех, кто планирует хранить в них автоматизированные тесты, написанные на разных языках программирования. Тут все просто: в Java тесты хранятся по полному имени пакет вроде io.qameta.allure, а в JavaScript или Python — просто по имени пакета. Это значит, что при автоматической генерации тест-кейсов из автотестов, каждый фреймворк будет городить свои подструктуры в дереве и вся нормализация и базовая структура будет нарушена. Конечно, можно написать свою интеграцию для каждого фреймворка, но мы же стараемся упростить себе жизнь, верно?

"Из коробки" роботы не всё делают одинаково.
"Из коробки" роботы не всё делают одинаково.

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

Как эту задачу решали Ops'ы?

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

Давайте рассмотрим его повнимательнее и попробуем применить к тестированию. Админы и все те, кто работают в Ops к метрикам и данным относятся с большой щепетильностью и любовью. Просто потому, что о падении сервиса, сети или недоступности какой-то кластера вы захотите узнать раньше пользователя, так? Изначально весь мониторинг строился по классической иерархической структуре: дата-центр → кластер → машинка → метрики (CPU, RAM, storage и прочее). Удобная и понятная система, которая работает, если не приходится в реальном времени отслеживать десяток метрик, которые не привязаны к физическим машинам. А метрики для Ops'ов очень важны.

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

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

Набор меток хранится в плоской структуре и свободно используется — любой критерий поиска, фильтрации или группировки становится меткой

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

Такой метод управления данными позволяет не только фильтровать и делать выборки внутри структуры. Он предоставляет еще один уровень свободы в виде вышеупомянутой группировки: теперь можно спокойно сделать запрос к хранилищу вида "покажи статистику доступности всех машин, на которых крутится такой-то микросервис с группировкой по кластерам". Парсер проходится по всем машинам, забирает статистику доступности с тех, на которых стоит метка микросервиса и группирует их по кластерам.

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

В любой момент по запросу пользователю доступна любая аналитика и любой срез данных. Зайдите в дэшборды любой Ops-команды крупного сервиса, — здесь найдутся отчеты по десятку метрик (uptime, загрузка ресурсов, количество пользователей и т.д.), нарезанных по множеству критериев (география, балансировка между серверами и пр.).

Да это же просто автоматизация папочек! — скажете вы.

И это прекрасно — это классическое решение проблемы масштабирования. Конечно, у системы с метками есть несколько минусы:

  • Нельзя создать "скелет" из папок и оставить их пустыми. Классическая практика из начала статьи, которая позволяет на старте продумать архитектуру.

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

Тест-кейсы: дерево против меток

— Хорошо, с админами все понятно. Они там сидят и целый день смотрят в метрики и крутят данные. А нам-то зачем?

Ответ прост: мир разработки, к сожалению или к счастью, уже давно ушел от жесткой структуры — релизы ускоряются, сборки автоматизируются. На фоне этих изменений, мир тестирования в большинстве компаний выглядит немного архаично: на новые фичи готовится по пачке новых тест-кейсов для ручных тестов и автоматизации, они раскладываются по папкам, запускается в тестирование на неопределенный срок (от 1-2 дней до недели), собирается результат тестирования и отгружается обратно в разработку после полного завершения. Ничего не напоминает? Это же старая добрая каскадная разработка (waterfall, то бишь)! В 2021 году. Если послушать Баруха Садогурского в одном из подкастов, где он довольно убедительно рассказывает, что любой процесс — это по сути agile, в котором "мы пытаемся отложить принятие решения максимально далеко, чтобы перед этим собрать побольше данных", станет понятно, почему весь мир разработки гонится за короткими итерациями и быстрыми релизами. Именно поэтому разработчики уже давно пишут софт итеративно, внедряя по одной фиче или паре фиксов на релиз, опсы отгружают эти релизы как можно скорее, которые перед этим тестируются. А как они тестируются?

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

Посмотрите на последние веяния в тестировании для DevOps заключаются в том, чтобы тестировать как можно меньше и как можно быстрее: это приводит к подходам вроде shift right и тестируйте как можно меньше. Практики, направленные на скорость, повторяемость и стабильность выполнения тестов, а не покрытие и оценку качества в широком смысле — про это в свое время буду писать отдельные статьи. Поэтому, чтобы оставаться в мире, где тестирование отвечает за качество продукта, давайте вернемся к нашим папочкам и признакам. Создавая папочную структуру, мы изначально закладываем в хранилище тест-кейсов принятое решение о том, в каком виде хотим получать отчеты и видеть результаты. Проблема в том, что мы не знаем какие отчёты понадобятся в будущем.

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

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

Пример представлений, которые можно получить в Allure TestOps в пару кликов из базы размеченных тестов.
Пример представлений, которые можно получить в Allure TestOps в пару кликов из базы размеченных тестов.

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

По сути, вместо одного статичного дерева, управление через признаки позволяет простым и понятным способом сделать генератор деревьев, основанный на нужных критериях, расширяемый и масштабируемый без лишних танцев с бубном. А как только мы получаем автоматически генерируемые выборки и группы, мы можем настроить автоматический live-репортинг и генерацию отчетов. Самый понятный пример — JIRA, где можно по любому полю тикета построить график, тренд или дэшборд любого вида, собрать, отфильтровать или сгруппировать тикеты (могут понадобиться плагины!:)) в любую структуру прямо на митинге.

Согласитесь, звучит заманчиво: иметь гибкость JIRA-тикетов в управлении тест-кейсами. Останется только автоматизировать запуски на слияние веток и вот тестирование уже отвечает требованиям DevOps!


Обсудить в форуме