что такое покрытие кода тестами

Code Coverage — хочу верить

Разработчик обязан знать свои инструменты! Знание инструментов увеличивает продуктивность, эффективность, производительность, потенцию разработчика! Не могу программировать без R#!

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

Правда, инструкция к инструменту обычно не содержит раздел «Противопоказания», не указываются ситуации когда НЕ стоит применять утилиту. Между тем, подобный раздел мог бы сэкономить тонны времени на неудачные эксперименты.

Сегодня я пошвыряю камни в огород Code Coverage (CC). Достаточно полезная метрика, под которой лежат несколько скудно документированных граблей.

«Есть ложь, есть наглая ложь
есть статистика».

Создатели SonarQube это великолепно понимают, недаром у SonarQube с десяток CC метрик. Я буду перебивать статистику используя CC от DevExpress, там метрика лишь одна.

Проблема 1. Типичный тест не того. Протестируем метод с кучей проверок аргумента:

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

Проблема 2. Замеряем актуальный код, вместо необходимого.

Тестируемый метод не содержит проверки на null аргумент, однако покрытие — 100%. Иногда люди забывают: Code Coverage — это метрика покрытия кода, не метрика закрытия требований; если в методе не достает логики (метод недостаточно сложен для решения своей задачи) — CC это не покажет.

100% покрытия не гарантируют работоспособности программы. Доводя до абсурда: пустой метод элементарно покрывается на 100%. Непустой метод покрывается на 100% тестами без Assert-ов.

Проблема 3. Оптимизм. Немного иное проявление предыдущей проблемы. Как видно, один тест покрывает 100% кода. Попробуем переписать наш метод, избавившись от LINQ (для улучшения производительности).

Получаем лишь 73% покрытия. Функциональность не изменилась, метрика упала. Мало того, что 100% покрытия не гарантируют работоспособности программы, эти 100% могут быть фейковыми. Вывод: LINQ — г**но результаты CC могут быть завышены, старайтесь проверять покрытие в редакторе.

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

Проблема 4. Передача ответственности.

Метод покрывается на 100% одним тестом. При этом покрытие OuterLib библиотеки лежит на совести того, кто её добавил. Или обновил. Года три назад, до введения CC. До увольнения.
Приходится снова констатировать факт: мало того, что 100% покрытия не гарантируют работоспособности программы, эти 100% могут быть фейковыми.

Помимо чисто кодовых моментов есть несколько претензий именно к обработке результатов CC

Претензия 0, всем известная. 100% покрытия. Нет 100% покрытия — нет одобрения билда. Проблема в том, что первые проценты покрытия получить относительно просто, а вот последние… Особенно, когда часть кода генерируется. Или недостижима (поскольку создана для Васи, который будет её юзать через два дня). Или просто теоретически достижима, а пример подбирать\высчитывать пару недель (такое бывает при работе с математикой). Короче, большинство команд (из тех кто вообще интегрирует CC в CI) останавливаются на 60\70\80 процентах необходимого покрытия.

Претензия 1, спорная. Покрытие мертвого кода. На моей памяти схожая проблема особо ярко проявилась в ходе проверки Mirand-ы коллегами из PVS. Комментарии довольно эмоциональны, но часть споров касалась мертвого кода: часть найденных диагностик указывала на (заброшенные) плагины, но не на ядро.

Возникает вопрос: нужен ли CodeCoverage для мертвого кода? С одной стороны, мертвый код это проблема, и привлечение внимания к нему приветствуется. С другой стороны, мертвый код не влияет на продакшн, так стоит ли позволять ему влиять на CC метрику?

Претензия 2. Важность кода. Расширение проблемы 1. В моем проекте есть два примечательных контроллера: «оплата» и «переговорка». «Оплата» критична для клиента, и я вполне согласен с требованием «80% покрытия», «переговоркой» же пользуются 1.5 анонимуса. В год. И она не менялась уже два года. Вопрос: для чего писать тесты к полумертвой функциональности? Лишь для получения 80% бейджа одобрения автосборки?

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

Претензия 4. Метрика «за бесплатно». Когда руководство скидывает требование «покрывайте код на 80%», и разработчики безропотно соглашаются. Проект при этом — одноразовый. Или прототип. Или дедлайн на носу. Или имеется здоровенный макаронный легаси монстр без единого теста.

Покрытие кода тестами требует времени! Если покрытие еще и замерять — время на тесты может и возрасти (хотя может и упасть). Так что если команда не успела сдать проект в срок, но зато достигла 80% покрытия — вина может поделиться между руководством и разработчиками. Вопрос линии раздела вины поднимать не стоит, ибо холивар.

Под конец. Еще раз замечу: СС — метрика полезная, хоть и с сюрпризами. Она реально помогает с контролем кода, если нет слепого стремления к цифрам в отчетах.

Источник

Оценка тестового покрытия на проекте

Самый лучший способ оценить, хорошо ли мы протестировали продукт – проанализировать пропущенные дефекты. Те, с которыми столкнулись наши пользователи, внедренцы, бизнес. По ним можно многое оценить: что мы проверили недостаточно тщательно, каким областям продукта стоит уделить больше внимания, какой вообще процент пропусков и какова динамика его изменений. С этой метрикой (пожалуй, самой распространённой в тестировании) всё хорошо, но… Когда мы выпустили продукт, и узнали о пропущенных ошибках, может быть уже слишком поздно: на “хабре” появилась про нас гневная статья, конкуренты стремительно распространяют критику, клиенты потеряли к нам доверие, руководство недовольно.

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

Зачем оценивать?

Как оценивать?

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

Оцениваем покрытие требований тестами

Допустим, у вас в команде есть аналитики, и они не зря тратят своё рабочее время. По результатам их работы созданы требования в RMS (Requirements Management System) – HP QC, MS TFS, IBM Doors, Jira (с доп. плагинами) и т.д. В эту систему они вносят требования, соответствующие требованиям к требованиям (простите за тавтологию). Эти требования атомарны, трассируемы, конкретны… В общем, идеальные условия для тестирования. Что мы можем сделать в таком случае? При использовании скриптового подхода – связывать требования и тесты. Ведём в той же системе тесты, делаем связку требование-тест, и в любой момент можем посмотреть отчёт, по каким требованиям тесты есть, по каким – нет, когда эти тесты были пройдены, и с каким результатом.
Получаем карту покрытия, все непокрытые требования покрываем, все счастливы и довольны, ошибок не пропускаем…

что такое покрытие кода тестами

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

Проблема: требования не атомарны.

Аналитики тоже иногда грешат винегретом в голове, и обычно это чревато проблемами со всем проектом. Например, вы разрабатываете текстовый редактор, и у вас могут быть в системе (в числе прочих) заведены два требования: «должно поддерживаться html-форматирование» и «при открытии файла неподдерживаемого формата, должно появляться всплывающее окно с вопросом». Сколько тестов требуется для базовой проверки 1-го требования? А для 2-го? Разница в ответах, скорее всего, примерно в сто раз. Мы не можем сказать, что при наличии хотя бы 1-го теста по 1-му требованию, этого достаточно – а вот про 2-е, скорее всего, вполне.

что такое покрытие кода тестами

Конечно, такой процесс согласования требует немало ресурсов и времени, особенно поначалу, до наработки практики. Поэтому проводите по нему только высокоприоритетные требования, и новые доработки. Со временем и остальные требования подтянете, и все будут счастливы! Но… а если требований нет вообще?

Проблема: требований нет вообще.

Они на проекте отсутствуют, обсуждаются устно, каждый делает, что хочет/может и как он понимает. Тестируем так же. Как результат, получаем огромное количество проблем не только в тестировании и разработке, но и изначально некорректной реализации фич – хотели совсем другого! Здесь я могу посоветовать вариант «определите и задокументируйте требования сами», и даже пару раз в своей практике использовала эту стратегию, но в 99% случаев таких ресурсов в команде тестирования нет – так что пойдём значительно менее ресурсоёмким путём:

что такое покрытие кода тестами

Но… Что делать, если требования ведутся, но не в трассируемом формате?

Проблема: требования не трассируемы.

На проекте есть огромное количество документации, аналитики печатают со скоростью 400 знаков в минуту, у вас есть спецификации, ТЗ, инструкции, справки (чаще всего это происходит по просьбе заказчика), и всё это выступает в роли требований, и на проекте уже все давно запутались, где какую информацию искать?
Повторяем предыдущий раздел, помогая всей команде навести порядок!

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

Проблема: требования всё время меняются.

Конечно, хорошо бы тестировать некую фиксированную систему, но наши продукты обычно живые. Что-то попросил заказчик, что-то изменилось во внешнем к нашему продукту законодательстве, а где-то аналитики нашли ошибку анализа позапрошлого года… Требования живут своей жизнью! Что же делать?

что такое покрытие кода тестами

В этом случае мы получаем все бенефиты оценки тестового покрытия, да ещё и в динамике! Все счастливы. Но…
Но вы так много внимания уделяли работе с требованиями, что теперь вам не хватает времени либо на тестирование, либо на документирование тестов. На мой взгляд (и тут есть место религиозному спору!) требования важнее тестов, и уж лучше так! Хотя бы они в порядке, и вся команда в курсе, и разработчики делают именно то, что нужно. НО НА ДОКУМЕНТИРОВАНИЕ ТЕСТОВ ВРЕМЕНИ НЕ ОСТАЁТСЯ!

Проблема: не хватает времени документировать тесты.

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

Но… Какое ещё «но»? Какое.

Говорите, все обойдём, и да пребудут с нами качественные продукты!

Источник

Покрытие кода

Что такое покрытие кода?

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

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

В этом уроке вы узнаете

Зачем использовать покрытие кода?

Вот несколько основных причин использования покрытия кода:

Методы покрытия кода

Ниже приведены основные методы покрытия кода.

Заявление покрытия

Что такое покрытие заявления?

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

Охват операторов используется для выведения сценария на основе структуры тестируемого кода.

что такое покрытие кода тестами

В White Box Testing тестер концентрируется на том, как работает программное обеспечение. Другими словами, тестер будет концентрироваться на внутренней работе исходного кода, касающегося управляющих потоковых диаграмм или блок-схем.

Давайте разберемся с этим на примере, как рассчитать покрытие выписки.

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

Исходный код:

Сценарий 1:

что такое покрытие кода тестами

Операторы, отмеченные желтым цветом, — это те операторы, которые выполняются в соответствии со сценарием.

Количество выполненных выписок = 5, Общее количество выписок = 7

Охват выписки: 5/7 = 71%

что такое покрытие кода тестами

Аналогично мы увидим сценарий 2,

Сценарий 2:

что такое покрытие кода тестами

Операторы, отмеченные желтым цветом, — это те операторы, которые выполняются согласно сценарию.

Количество выполненных заявлений = 6

Общее количество заявлений = 7

что такое покрытие кода тестами

Охват выписки: 6/7 = 85%

что такое покрытие кода тестами

Но в целом, если вы видите, все утверждения охватываются 2- м сценарием. Таким образом, мы можем сделать вывод, что общий охват отчетности составляет 100%.

что такое покрытие кода тестами

Что входит в покрытие заявления?

Охват решений

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

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

что такое покрытие кода тестами

Пример покрытия решения

Рассмотрим следующий код:

Сценарий 1:

что такое покрытие кода тестами

Код, выделенный желтым цветом, будет выполнен. Здесь «Нет» результат решения If (a> 5) проверяется.

Сценарий 2:

что такое покрытие кода тестами

Код, выделенный желтым цветом, будет выполнен. Здесь «Да» результат решения Если (а> 5) проверяется.

ПрецедентЗначение АВыводОхват решений
12250%
261850%

Охват филиала

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

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

Используя метод покрытия Branch, вы также можете измерить долю независимых сегментов кода. Это также поможет вам узнать, какие разделы кода не имеют ветвей.

Формула для расчета покрытия филиала:

что такое покрытие кода тестами

Пример покрытия филиала

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

Рассмотрим следующий код

что такое покрытие кода тестами

Покрытие филиала также будет учитывать безусловное отделение

ПрецедентЗначение АВыводОхват решенийОхват филиала
12250% 33%
261850% 67%

Преимущества покрытия филиала:

Тестирование покрытия филиала предлагает следующие преимущества:

Состояние покрытия

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

Например, если в выражении есть логические операции, такие как AND, OR, XOR, которые указывают общие возможности.

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

Формула для расчета покрытия условий:

что такое покрытие кода тестами

что такое покрытие кода тестами

Для приведенного выше выражения у нас есть 4 возможных комбинации

Рассмотрим следующий вход

Состояние покрытия = 25%

Покрытие конечного автомата

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

Какой тип покрытия кода выбрать

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

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

Покрытие кода против функционального покрытия

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

Инструменты покрытия кода

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

Источник

Визуализация покрытия автотестами

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

что такое покрытие кода тестами

Под катом — видео и расшифровка доклада Артема Ерошенко из Qameta Software с конференции Heisenbug. Он представил несколько разработанных простых и элегантных решений, которые помогают команде Яндекс.Вертикалей оценивать покрытие тестов, написанных автоматизаторами тестирования. Артем расскажет, как можно быстро узнавать, что покрыто, как покрыто, какие тесты прошли, и мгновенно смотреть наглядные отчеты.

Меня зовут Артем Ерошенко eroshenkoam, я занимаюсь автоматизацией тестирования уже более 10 лет. Я был автоматизатором тестирования, менеджером команды разработки инструментов, разработчиком инструментов.

На данный момент я консультант в области автоматизации тестирования, работаю с несколькими компаниями, с которыми мы выстраиваем процессы.
Я также являюсь разработчиком и негласным менеджером Allure Report. Недавно мы поправили прикольную штуку: теперь в JUnit 5 есть fixtures.

Atlas Framework

Моя разработка — Atlas Framework. Если кто-то начинал автоматизировать в 2012 году, когда веб-драйверы Java только начинали свой путь, в этот момент я сделал из опенсорса библиотеку, которая называется HTML Elements.

Html Elements имеет свое продолжение и переосмысление в библиотеке Atlas, которая построена на интерфейсах: там нет классов как таковых, нет полей, очень удобная, легковесная и легко расширяемая библиотека. Если у вас есть желание в ней разобраться, можете прочитать статью или посмотреть доклад.

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

Как устроена автоматизация в Вертикалях?

В команде по автоматизации тестирования Яндекс.Вертикалей всего четыре человека, которые автоматизируют четыре сервиса: Яндекс.Авто, Работа, Недвижимость и Запчасти. То есть это небольшая команда автоматизаторов, которые делают очень много. Мы автоматизируем API, веб-интерфейс, мобильные приложения и так далее. Всего у нас где-то около 15,5 тысяч тестов, которые выполняются на разных уровнях.

Стабильность тестов в команде составляет около 97%, хотя некоторые мои коллеги говорят о 99%. Такая высокая стабильность достигается именно благодаря коротким тестам на очень нативных технологиях. Как правило, наши тесты занимают около 15 минут, что очень емко, и мы запускаем их примерно в 800 потоков. То есть у нас 800 браузеров стартуют одновременно — такой стресс-тест нашего testing’а. В качестве железа мы используем Selenoid (Aerokube). Подробнее об автоматизации тестирования в Яндекс.Вертикалях можно узнать, посмотрев мой доклад 2017 года, который до сих пор актуален.

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

В Вертикалях тесты пишут разработчики тестов, причем они настолько сильно увлеклись разработкой тестов, что конкурируют с нами. Об этом процессе подробнее можно узнать из доклада «Полный цикл тестирования React-приложений», где Алексей Андросов и Наталья Стусь рассказывают, как они пишут Unit-тесты на Puppeteer параллельно с нашими Java end-to-end тестами.

В нашей команде тесты пишут и инженеры по автоматизации тестирования. Но зачастую мы занимаемся развитием каких-то новых подходов по их оптимизации. Например, мы внедряли скриншотное тестирование, тестирование через моки, сокращение тестирования. В общем, наше направление в основном — software developer in test(SDET), мы больше про то, как надо писать тесты, а тестовая база наполняется отчасти нами и поддерживается ручными тестировщиками.

Разработчики нам тоже помогают, и это круто.

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

Что тестируется, а что нет?

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

Как измеряется покрытие требований

Рассмотрим покрытие требований на примере auto.ru. На месте тестировщика auto.ru я бы сделал следующее. Во-первых, я бы погуглил и сразу бы нашел специальную таблицу требований. Это и есть основа покрытий требований.

что такое покрытие кода тестами

В этой таблице названия требований выписаны слева. В данном случае: аккаунт, объявления, проверка и оплата, то есть проверка объявления. В целом, это и есть покрытие. Детализация левой части зависит от уровня тестировщика. Например, у инженеров из Google есть 49 типов покрытий, которые проверяются на разных уровнях.

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

что такое покрытие кода тестами

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

что такое покрытие кода тестами

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

Какие у этого подхода есть «плюсы и минусы»? Плюс в том, что этот подход отвечает на наши вопросы. Если менеджер спросит, что у нас покрыто, я открою табличку и покажу, какие фичи покрыты. С другой стороны, эти требования надо всегда держать в актуальном состоянии, а они очень быстро устаревают.
Когда у вас 15 тысяч тестов, то смотреть на TestRail — это все равно, что смотреть на звезду в космосе: она взорвалась уже давно, а свет до вас дошел только сейчас. Вы смотрите на актуальный тест-кейс, а он уже устарел давно и безвозвратно.

Эту проблему сложно решить. Для нас это вообще два разных мира: есть мир автоматизации, который крутится по своим законам, где каждый упавший тест сразу же фиксится, а есть мир ручного тестирования и карт требований. Стена между ними — непробиваемая, если только вы не используете Allure Server. Мы сейчас эту задачу для них как раз и решаем.

Третий пункт «плюсов и минусов» — необходимость ручной работы. Вам в новом проекте нужно заново создавать карту требований, писать все тест-кейсы и так далее. Это всегда требует ручной работы, и это на самом деле очень печально.

Как измеряется покрытие кода

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

что такое покрытие кода тестами

Здесь отражено покрытие по package, точнее маленькая часть того, что на самом деле обычно есть в продукте. Слева написаны package, как раньше были написаны фичи. То есть наше покрытие наконец-то привязывается к каким-то осязаемым штукам, в данном случае — Package. Справа написаны атрибуты: покрытия по классам, покрытия по методам, покрытия по блокам кода и покрытие по строчкам кода.
Процесс сбора покрытия состоит в том, чтобы понять, по какой строчке кода тест проходил, а по какой — нет. Это довольно несложная задача, но в последнее время очень актуальная.

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

Итак, у нас есть тест, который взаимодействует с системой. Неважно, как он с ней взаимодействует: через фронтенд, API или напрямую лезет в бэкенд — просто будем считать, что он у нас есть.

Затем следует сделать инструментирование. Это некоторый процесс, который позволяет понять, какие строчки кода проверялись, а какие нет. Не надо его подробно изучать, надо просто поискать название вашего фреймворка, на котором вы пишете, скажем, Spring, затем instrumentation, и coverage — по этим трем словам поймете, как это делается.

Когда ваши тесты проверяют, на какую строчку кода попал тест, а на какую не попал, они сохраняют файлы с информацией о том, какие строчки покрыты. На основе этой информации у вас появляются данные.

Какие «плюсы и минусы» у покрытия кода?

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

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

что такое покрытие кода тестами

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

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

Поэтому у нас появилась идея: а что если взять лучшее от каждого? Так, чтобы покрытие отвечало на наши вопросы, всегда было актуально и требовало только настройки. Нам надо просто взглянуть на покрытие под другим углом, то есть взять за основу покрытия другую систему. При этом сделать так, чтобы оно собиралось полностью автоматически и приносило кучу пользы. И для этого мы перейдем в покрытие для API тестов.

Покрытие API тестов

Что лежит в основе покрытия? Для этого мы используем Swagger — это API для документации. Сейчас я не представляю свою работу без Swagger, это инструмент, который у меня постоянно используется для тестирования. Если вы не пользуетесь Swagger, я крайне рекомендую зайти на сайт и ознакомиться. Там вы сразу же увидите очень интуитивный и понятный пример использования.
По сути, Swagger представляет из себя документацию, которая генерируется по вашему сервису. Она содержит:

Принцип работы Swagger — это генерация. Неважно, какой фреймворк вы используете. Допустим, Spring либо Go Server, вы используете компонент Swagger Codegen и генерируете swagger.json. Это некоторая спецификация, на основе которой потом рисуется красивый UI.
Для нас важно, что используется именно swagger.json: его поддержка есть для всех широко используемых языков.
У нас есть Open API спецификация swagger.json. Она выглядит так:

что такое покрытие кода тестами

Запросы выглядят примерно таким образом: summary, description, коды ответов и «ручка» (path: /users). Также есть информация о параметре запросов: все структурировано, есть параметр user ID, он находится в пути, где есть required, такой-то description и type — integer.

что такое покрытие кода тестами

Есть коды ответов, они тоже все задокументированы:

что такое покрытие кода тестами

И нам пришла в голову идея: у нас есть сервис, который генерирует Swagger, и мы захотели в тестах сохранять такой же Swagger, чтобы потом их сравнить. Другими словами, когда пробегают тесты, они генерируют ровно такой же Swagger, мы его кидаем на Swagger Diff, понимаем, какие параметры, ручки, статус коды у нас проверены и так далее. Это то же самое инструментирование, тот же самый coverage, только наконец-то в требованиях, которые мы понимаем.

А что если построить дифф?

Мы обратились к библиотеке Swagger diff, которая для этого и нужна. Ее принцип работы примерно такой: у вас есть версия 1.0, при V версия API 1.1, они оба генерируют swagger.json, потом вы их кидаете на Swagger diff и смотрите результат.
Результат выглядит примерно таким образом:

что такое покрытие кода тестами

У вас есть информация, что появилась, например, новая ручка. У вас также есть информация о том, что удалилось. Это значит, что тесты пора удалять, они уже неактуальны. С появлением информации об изменениях меняются и параметры, таким образом, очевидно, что в этот момент упадут ваши тесты.

Нам понравилась эта идея, и мы начали имплементировать. Как мы решили делать: у нас есть «эталонный» Swagger, который генерирует с кода разработчиков, у нас также есть API тесты, которые будут генерировать свой Swagger, и мы между ними сделаем diff.

Итак, мы запускаем тесты на сервис: у нас есть Rest Assured, который сам обращается к сервисам на API. И мы его инструментируем. Здесь есть подход: можно сделать фильтры, на него уходит запрос — и он сохраняет информацию о запросе в виде swagger.json прямо под себя.
Вот весь код, который нам надо было написать, там было 69-70 строчек — это очень простой код.

что такое покрытие кода тестами

Самое смешное, что мы использовали нативный клиент для Swagger, писали прямо там. Нам даже не надо было создавать свои bin-ы, просто наполняли спецификацию Swagger.

что такое покрытие кода тестами

Итак, мы были почти в двух шагах от победы, но в результате отказались от Swagger Diff, потому что он работает немного в другой концепции — в концепции дифа.

Swagger Diff говорит, что изменилось, а не что покрыто, а мы хотели отображать именно результат покрытия. Там очень много лишних данных, он хранит в себе информацию о description, summary и другую метаинформацию, а у нас этой информации нет. И когда мы делаем Diff, нам пишут, что «у этой ручки отсутствует description», а его и не было.

Свой отчет

Мы сделали свою имплементацию, и она работает следующим образом: у нас есть много файлов, которые пришли с автотестов, есть API service Swagger, и мы на основе его генерируем отчет.
Простой отчет выглядит так: сверху видно информацию, сколько всего ручек (349), информацию о том, которые покрыты полностью (каждый параметр, статус-код и так далее покрыт). Можно выбрать свои критерии, например, покрыть несколько параметров.

Здесь также есть информация, что 40% покрыто частично — это значит, что у нас уже есть тесты на эти ручки, но некоторые вещи еще не покрыты, и нужно туда внимательно посмотреть. Отражено также Empty-покрытие.

что такое покрытие кода тестами

Давайте пройдемся по tab-ам. Это full-покрытие, мы видим все параметры, которые у нас есть, которые покрываются, статус-коды и так далее.

что такое покрытие кода тестами

Потом у нас есть частичное покрытие. Мы видим, что у нас на ручку login-social один параметр покрыт, а два — нет. Причем мы можем развернуть ее и посмотреть, какие конкретно параметры и статус-коды покрыты. И в этот момент разработчику становится очень удобно: версии приложения у нас катятся очень быстро, и мы зачастую можем забыть какие-то параметры.

что такое покрытие кода тестами

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

Последнее — Glory of shame, нам еще предстоит это делать. Когда смотришь на эту страничку и видишь там Empty:172 — руки опускаются, и тогда начинаешь обучать ручных тестировщиков писать автотесты, в этом и смысл.

что такое покрытие кода тестами

Какую пользу мы получили, когда выкатили свое решение?

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

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

Идеи по развитию

Во-первых, очень не хочется держать второй отчет, а хочется интегрировать его в Swagger UI. Это мой любимый «Photoshop Edition report»: фишка, которую я разрабатывал в последнее время. Тут сразу же есть информация о параметрах, которые у нас протестированы, а которые нет. И было бы круто отдавать эту информацию сразу вместе со Swagger-ом.

что такое покрытие кода тестами

Например, фронтендер может сам посмотреть, какие параметры еще не протестированы, расставить приоритеты и решить, что пока их не нужно брать в разработку, ведь неизвестно, насколько хорошо они работают. Или бэкэндер пишет новую ручку, видит красное и пинает тестировщиков, чтобы все было зеленое. Это сделать довольно несложно, мы идем в этом направлении.

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

Третья идея по развитию — это интеграция с Allure Report. Я вижу это вот так:

что такое покрытие кода тестами

Как правило, когда параметр «протестирован», это не всегда говорит нам о том, как он протестирован. И хочется навести на этот параметр и увидеть конкретные шаги теста.

Покрытие для Web-тестов

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

что такое покрытие кода тестами

Если посмотреть на ваш сайт — это некоторый набор элементов и способов взаимодействия с ними. Это полное описание: «элемент — способ с ним взаимодействовать». На ссылку можно кликнуть, текст можно скопировать, в input можно что-то вбить. Сайт в целом состоит из элементов и способов их взаимодействия:

что такое покрытие кода тестами

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

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

что такое покрытие кода тестами

Я хочу навести на этот элемент и увидеть все тесты, которые у нас есть на этот элемент. Если бы такой инструмент был, я был бы счастлив. Когда мы начали думать про эту идею, то, в первую очередь, посмотрели на Яндекс.Метрику. У них на самом деле есть примерно подобная функциональность по карте ссылок. Хорошая идея.

Суть в том, что они подсвечены ровно так, словно уже дают нужную нам информацию. Они говорят: «Вот по этой ссылке проходили 14 раз», что в переводе на язык тестирования значит: «в этой ссылке тестировали 14 тестов» и так или иначе через нее прошли. А вот на эту красную ссылку уходило аж 120 тестов, какие интересные тесты!

Можно рисовать всякие тренды, добавлять метаинформацию, но что будет, если мы это все возьмем и нарисуем с точки зрения тестирования? Итак, у нас задача: навести на какой-то элемент и получить заметку со списком тестов.

что такое покрытие кода тестами

Для того, чтобы это имплементировать, надо кликнуть на иконку, затем написать заметку, и это — весь наш тест. Мы у себя используем Atlas, и интеграция пока есть только с ним.
Atlas выглядит примерно так:

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

Потом сохраняем в input User_Text и сабмиттим ее.

После этого проверяем, что текст ровно тот, который должен был быть.

Потом этот лог прикрепляем к Allure в виде каждого теста, и когда у нас появляется много locators.json — мы генерируем meta.json. Схема одна и та же для всех элементов.

У нас есть плагин для Google Chrome. Мы захотели сделать решение в виде плагина. Я специально сделал кривой скриншот, чтобы на слайде была видна одна важная деталь — path to locators.json.

что такое покрытие кода тестами

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

что такое покрытие кода тестами

У каждого элемента появляется количество тестов, которые через него проходят: видно, что 40 тестов проходят через «купить квартиру», header тестируется по одному тесту, это прикольно, и опция «квартиру» тоже отображается. У вас получается полная карта покрытия.

Если вы наведете на какой-то элемент, он возьмет данные и отпечатает ваши реальные тесты с вашей tms, Allure Board и так далее. В результате появляется полная информация о том, что тестируется и каким образом.
Учтите, что из каждого теста можно провалиться прямо в Allure-отчет.

что такое покрытие кода тестами

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

Какой профит?

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

Теперь любой может зайти и найти любую «нитку», которая ведет к сценарию. Например, вы предполагаете, что нужно протестировать оплату. Оплата, очевидно, ведет через кнопку оплаты: нажимаете — появляются все тесты, которые проходят через кнопку оплаты. Это чудесно! Вы заходите в любой из них и просматриваете сценарий.

Более того, вы понимаете, что проверялось раньше. У нас генерируется статический файл, вы можете указать к нему путь и указать, какие тесты были две недели назад. Если менеджер, говорит, что в продакшене баг и спрашивает, тестировали ли мы пару недель назад такую-то функциональность, вы берете репорт Allure, говорите, например, что не тестировали.

Еще один профит — ревью после автоматизации тестирования. До этого у нас было ревью до автоматизации тестирования, сейчас же можно делать свои тесты ровно так, как вы их видите. Захотели сделать тест — сделали, отвели какой-то branch, запустили Allure, скинули ссылку на плагин ручному тестировщику и попросили посмотреть тесты. Это именно тот процесс, который позволит вам усилить Agile-стратегию: тимлид делает ревью кода, а ручные тестировщики — ваших тестов (сценариев).

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

что такое покрытие кода тестами

И если у нас переверстается блок «цена от», то ничего страшного, упадет один тест, человек его поправит. Если же изменить блок с 87-ю тестами, то покрытие сильно просядет, потому что 87 тестов не пройдут и не проверят какой-то результат. К этому блоку нужно повышенное внимание. Тогда нужно сообщить разработчику, что этот блок обязательно должен быть с ID, потому что если он уйдет — все развалится.

Как можно развиваться дальше?

Например, можно идти по пути развития поддержки для других тулов, например, для Selenide. Хочется даже поддержать не конкретный Selenide, а реализацию драйвера, которая позволит собирать locators, вне зависимости от тулы, которую вы используете. Этот прокси будет дампить информацию и после этого отображать.

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

что такое покрытие кода тестами

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

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

что такое покрытие кода тестами

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

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

Таким образом, при наличии Java-тестов и тестов на Puppeteer, которые пишет другая команда, мы можем посмотреть какую-то конкретную страницу и сразу сказать, где у нас тесты пересекаются. То есть мы будем разговаривать с ними на одном языке, и нам не надо будет по крупицам собирать эту информацию. Если у нас есть такой тул, который показывает все в веб-интерфейсе, то задача сравнения тестов на Java и Puppeteer уже не кажется нерешаемой.

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

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

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

Источник

Добавить комментарий

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