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

Суть

Покрытие кода — это процент кода, покрытый тестами.

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

В большинстве случаев, когда говорят о покрытии кода, имеют в виду юнит-тестирование (модульное, выполняемое разработчиками); когда говорят о тестовом покрытии, это обычно относится к тестированию «в общем» (ко всем другим видам и уровням тестирования, которое выполняется QA-инженерами/QA-департаментом). О тестовом покрытии — отдельный материал.

Почему важен показатель тестового покрытия

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

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

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

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

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

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

Четвертое: добросовестно проведенные юнит-тесты сокращают объем тестирования на высших уровнях «пирамиды». Разработчики экономят время тестировщиков.

Далее рассмотрим самые применяемые метрики покрытия кода.

Типы покрытия кода

Покрытие операторов (statement coverage)

Суть : каждый оператор должен быть выполнен хотя бы один раз.

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

Показатель покрытия операторов:

(Количество выполненных операторов / Общее количество операторов) * 100

Покрытие операторов имеет такие полезные функции:

  • Проверить логику кода
  • Найти «мертвый код», незадействованные операторы
  • Проверить пути выполнения и найти среди них непокрытые 

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

Программа на условном ЯП (псевдокод), суммирующая два числа и выводящая разные результаты, если результат меньше/равен/больше 0:

Unittest1: SUM(a,b)

result = a + b;
if result > 0 then
print(‘Больше нуля’);
else if result < 0 then
print(‘Меньше нуля’);
else
print(‘Равно 0’);
end

Каким будет покрытие операторов здесь? В первом операторе ввод, например, a=3, b=5. Будут выполнены операторы в строках 1-4. Таким образом, покрытие операторов составит 4 оператора из 8 имеющихся, то есть 50%.

Примем a=3, b=-5. Тогда будут выполнены операторы в строках 1,2,3,5,6. В первом и втором тестах будут вызваны и выполнены операторы в строках с 1 по 6, то есть 6 из 8 строк, покрытие операторов ( = строк) составит 75%.

Покрытие ветвей (branch coverage)

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

(Количество выполненных ветвей / Общее количество ветвей)* 100

Что дает покрытие ветвей:

  • Проверяет полноту покрытия решений
  • А также проявляет возможное некорректное поведение каждой ветви
  • И, что важнее, проверяет участки кода, труднодоступные для других методов оценки покрытия

Пример покрытия ветвлений

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

Unittest2: EVEN(a)

if a is even then
print(‘Четное’);
print(a);

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

Покрытие кода тестами - Покрытие решений
Покрытие кода тестами — Покрытие решений

На рисунке два условных ветвления, “Да” и “Нет”. Стрелкой без подписи обозначено ветвление без условия (unconditional branch) — метод покрытия ветвей учитывает и эти ветви. Имеем два тестовых сценария:

  1. Например a = 1. Выполнение пойдет по ветви “Нет”. Тогда покрытие ветвей составит ⅓ строк, 33%.
  2. Примем a = 4; Выполнение пойдет по ветви “Да” и по ветке без условия, и покрытие составит ⅔ = 67%. Покрытие кода составит 33%+67%=100%.

Покрытие функций (function coverage)

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

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

(Количество выполненных функций / Общее количество функций)* 100

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

Как видим выше, высокое, даже 100%-ное покрытие кода не всегда гарантирует, что в коде нет багов.

Идеальное покрытие

Когда говорят об «идеальном покрытии», имеют в виду 100% или около того — тогда код должен быть близок к совершенству. Все сложнее.

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

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

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

Ну и в-третьих, 100%-ное покрытие кода вовсе не гарантирует качества — все зависит от подходов и метрик. Кроме того, функции могут не иметь багов, и быть отлично протестированными, но работать некорректно совсем по другим причинам. 

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

Инструменты

Инструменты оценки покрытия кода на самых популярных ЯП

JavaScript: Istambul

Для JavaScript есть удобный инструмент. Поддерживает ES5 и ES2015+. Интегрируется с фреймворками юнит-тестирования на JS: tap, mocha, AVA. Открытый и бесплатный.

Сайт Istambul

Python: Coverage.py

Для Python есть Coverage.py, тоже открытый и бесплатный. CLI, API, интеграция с тестраннерами.

Сайт Coverage.py

Java: JaCoCo

Для java-разработчиков. Поддерживается Eclipse Foundation. Легко интегрируется с Gradle, Maven, IntelliJ IDEA, Eclipse. Обширные и детализированные репорты по покрытию кода. Открытые исходники, бесплатный.

Сайт

.NET: NCover

Решение корпоративного уровня для .NET, мощное и богатое функциями. Поэтому платное и с закрытым кодом.

Сайт NCover

Какой была ваша первая зарплата в QA и как вы искали первую работу?

Мега обсуждение в нашем телеграм-канале о поиске первой работы. Обмен опытом и мнения.

Подписаться
Уведомить о
guest

0 комментариев
Межтекстовые Отзывы
Посмотреть все комментарии

Мы в Telegram

Наш официальный канал
Полезные материалы и тесты
Готовимся к собеседованию
Project- и Product-менеджмент

🔥 Популярное

💬 Telegram-обсуждения

Наши подписчики обсуждают, как искали первую работу в QA. Некоторые ищут ее прямо сейчас.
Наши подписчики рассказывают о том, как не бояться задавать тупые вопросы и чувствовать себя уверенно в новой команде.
Обсуждаем, куда лучше податься - в менеджмент или по технической ветке?
Говорим о конфликтных ситуациях в команде и о том, как их избежать
$1100*
медианная зарплата в QA в июне 2023

*по результатам опроса QA-инженеров в нашем телеграм-канале

Собеседование

19%*
IT-специалистов переехало или приняло решение о переезде из России по состоянию на конец марта 2022

*по результатам опроса в нашем телеграм-канале

live

Обсуждают сейчас