Pull to refresh

Comments 32

Проблема №1 прекрасно иллюстрирует, что любая планка ниже 100% приводит к тому, что покрывается то что легче, а не то что нужно.

Есть ещё и такое мнение.
Помечать код как «Не анализировать покрытие» — подход заслуживающий права на жизнь. К сожалению, им тоже можно злоупотребить. Доводя до абсурда — можно пометить весь код «неанализируемым».
Но статья отличная, спасибо за линк.
Пометка будет иметь объяснение и коммитера.
Несколько недостатков по-прежнему остается.
Например, 'commited by Vasya, «Will test later, deadline»'. Или проекты где анализ внедряется после 5 лет разработки: в наличии миллион строк кода, покрытие — 50%. Метить непокрытый код проблемно, придется реагировать на изменения.

Но в целом вариант очень даже интересный, с явными преимуществами перед 80% покрытия.
В последнем предложении взаимоисключающие параграфы, не?
Если не гнаться за цифрами, то это не метрика.
Интересно, существуют ли тулзы для вычисления code coverage, которые могут игнорировать не-покрытие фрагмента кода, если рядом с ним есть сигнальный комментарий. Казалось бы, в таком случае правило «весь код должен быть покрыт на 100% либо иметь разумную причину быть не покрытым, выраженную в комментарии» решает большую часть проблем, указанных в статье.
Думаю, зависит от языка\инструмента. По ссылке от andy128k (см. первый комментарий) можно найти вот этот пример.

Обычно ведь покрытие тестами кода должно говорить не то, что код покрыт на 60%, а то, что в 40% кода тесты вообще не смогли зайти. Или по-другому: разработчик не способен написать такие интеграционные или модульные тесты, которые бы зашли в эти 40% (за приемлемое время).


То есть правильная характеристика — не покрытие кода, а скорее "мера непокрытого кода".


Ну и конечно — адекватность тестов должна проверяться отдельно на code review, тут уже никто не спорит. Накрутки тестов и покрытие должны исключаться и удаляться.

Еще лучше: проверять адекватность тестов\CC еще в процессе разработки. Во время CodeReview проблемно проверить какие именно участки код покрыты.

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

Несомненно, предварительный просмотр кода CC утилитой не отменяет CodeReview, однако и CodeReview предварительного просмотра полностью не заменит.

Не забывайте что есть другие подходы, например Property Based Testing или Mutation Testing, которые друг друга дополняют и могут заменить классический ААА путь написания тестов. Но защиты от сумасшедшего индуса дурка нет.

Любой процент ппокрытия не говорит вообще ничего, потому что эта метрика никак не связана с качеством тестов.
Пример:
if(a > 5){

} else {

}
Вы пишете тест где а = 10 и а = 3. Анализ покрытия скажет вам, что код протестен на 100%. Но говорит ли этот факт о том, что условие действительно корректно протестено? Конечно нет, ибо если вдруг поменяем условие на а >=5 тесты все еще будут зелеными, хотя поведение программы изменилось.

Поэтому можно говорить только о том, что покрытие в 70% наверное лутше чем в 50% и не более того.

Что бы улутшить ситуацию, надо тестить сами тесты. Например через mutation testing. На хабре есть статьи на эту тему, очень рекомендую.
Анализ покрытия скажет вам, что код протестен на 100%

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

Вы пишете тест где а = 10 и а = 3.

Наш код стоит тестировать примерами a=5 и a=4, как два граничных случая. Соответственно, появится красный тест при изменении условия на a >= 5.

Любой процент ппокрытия не говорит вообще ничего, потому что эта метрика никак не связана с качеством тестов.

Вы несколько категоричны. Метрика действительно может иметь расхождение с качеством приложения\тестов, однако она предоставляет первичную оценку, что уже неплохо. Иначе бы CC не использовали. Плюс, CC — это не только метрика. В случае .NET есть CC утилита, подсвечивающая посещенные\непосещенные тестами куски кода, что весьма помогает при написании тестов.

Что до мутационного тестирования — это (интересная) тема отдельных статей на хабре.

Мутацинное тестирование (и/или фаззинг) это приятное дополнение к покрытию, а не замена.
Я бы посоветовал относиться к покрытию кода как температуре тела — 36.6 не говорит, что человек здоров, но большие отклонения от нормы обычно говорят о серьезных проблемах.
Нужно ли мерить покрытие кода авто-тестами? Мое мнение — обязательно. И в первую очередь не ради магической цифры, а для анализа результатов.
Да, как и любую другую метрику ее можно скомпрометировать.
Да, метрика является линейной — не может отличить полезный код от мало- или бесполезного. Но если фокусироваться на анализе, то смотреть можно на покрытие отдельных компонент или библиотек. При желании можно как-то разметить код и получить нелинейную метрику (примерно как раскладка багов по северити).
Да, метрика не показывает отсутствующие ветки кода или покрытие граничных условий. Примите как ограничение. Покрытие требований избавлено от этих недостатков? Вы все граничные условия прописываете в требования?

Я бы выделил следующие сильные стороны измерения и анализа покрытия кода по сравнению с покрытием требований:
1. тестовое покрытие можно мерить при отсутствии требований или других артефактов.
2. метрика инструментальная, т.е. ее получение обычно относительно недорого (в плане трудозатрат).
3. Т.ч. процесс измерений автоматизирован, то исключен человеческий фактор — труднее манипулировать результатом.
4. Т.к. процесс относительно дешев, то можно мерить часто и отслеживать тренды.

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

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

СС — это технологическая метрика. Она не много говорит о качестве программного продукта. Зато кое-что говорит о качестве процесса его разработки!

Пример:
Предположим, на следующий год вы можете влиться в одну из двух команд.
Всё примерно одинаково: по 4 человека в командах, тип приложения в обоих случаях "как вы любите", размеры исходного кода, количество пользователей, выручка… всё примерно одинаково.
Но в одном случае у проекта на дашборде светится 62.4% code coverage (а на начало прошлого года — 55%), а у другого проекта этой цифры вообще нет и никто даже примерно ее не знает.
В какую команду вы пойдете?

В какую команду вы пойдете?

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

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

А почему юнит тест не может это покрыть?

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

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

Если это большой метод, то почему нельзя его вынести в отдельный класс или написать test-specific descendant для тестирования или сделать публичным, если это маленький метод почему нельзя чтобы коллега его добавил при разработке.

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

Остальные сценарии (перенести в класс, сделать публичным, оставить Васе) тоже имеют право на жизнь, однако могут привнести свои сложности.

В итоге мы получим некоторое количество геморроя лишь для «100% покрытия».

Возвращаясь к оригинальной фразе (часть кода… недостижима (поскольку создана для Васи, который будет её юзать через два дня).) — вы правы, с недостижимостью я косякнул.

Фактически вы разрабатваете что-то что используется Васей как отдельный модуль. То есть есть high cohension внутри этого метода и low coupling с Васиным кодом. Сам по себе факт того, что это надо это признак для рефакторинга. Тесты нужны и для того, чтобы выявлять такие моменты.

Покрытие тестами — это метрика, того как на фирме относятся к качеству кода.

Наличие на предприятии директора по качеству, ОТК и сертификатов качества, еще не говорит, что продукт качественный(директор — разгильдяй, сертификаты липовые), но по крайней мере на этом заводе знают слово «качество»)))

Для меня тесты — это не только показатель работоспособности кода, но и инструмент для написания более архитектурно грамотного, качественного кода. Следуя TDD проблемные места видны заранее, еще до того как был реализован класс.
По этой причине низкое покрытие тестами может быть сигналом о том, что присутствуют архитектурные проблемы. На практике я заметил, что практически всегда тот код, который нельзя/сложно протестировать — код низкого качества.
Поэтому я стараюсь достигать как можно больших значений CC, пытаясь не "читерить".

ниодин code coverage tool еще не смог показать честное покрытие. Особенно, в Javascript, где особенности языка позволяют еще большие трюки, чем в Java. Поэтому эти метрики носят лишь рекомендательный сферический характер. Чтоб покрыть функционал ( а не строки кода) на 100%, нужны хорошие тесты. Разработчики часто не умеют или не хотят тратить на это время. Тесты становятся болью, теряется смысл их написания и поддержки.
ниодин code coverage tool еще не смог показать честное покрытие
Странно, у меня совсем другой опыт: любой code coverage tool показывает честное покрытие до тех пор, пока вы не пытаетесь его обойти. Может, от языка зависит.
Sign up to leave a comment.

Articles