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

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

Тестирование

Код без тестов

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

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

Баг при котором исполняется не ожидаемый код

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

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

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

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

Мертвый код

Старый код, который уже нигде не используется

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

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

Мертвый код в тестах

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

Заключение

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