Что такое тестовое покрытие (code coverage)?

Ответ

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

Уровни покрытия (от простого к сложному):

  1. Покрытие строк — процент выполненных строк кода
  2. Покрытие ветвей — процент пройденных условных переходов (if/else, case)
  3. Покрытие путей — процент уникальных последовательностей выполнения
  4. Покрытие условий — процент проверенных булевых подвыражений

Пример измерения в JavaScript (Jest + Istanbul):

// package.json
{
  "scripts": {
    "test": "jest --coverage",
    "test:watch": "jest --coverage --watchAll"
  }
}
// math.js
function divide(a, b) {
  if (b === 0) {          // Ветвь 1
    throw new Error('Division by zero');
  }
  return a / b;           // Ветвь 2
}

// math.test.js
test('divide throws on zero', () => {
  expect(() => divide(10, 0)).toThrow();  // Проверяет только ветвь 1
});
// Не хватает теста для ветви 2 → покрытие ветвей 50%

Инструменты для разных языков:

  • Java: JaCoCo, Cobertura
  • Python: coverage.py, pytest-cov
  • C#: Coverlet, dotCover
  • Go: go test -cover

Критические ограничения метрики:

  • Ложное чувство безопасности — 100% покрытие ≠ отсутствие багов
  • Не измеряет корректность — тест может проходить, но проверять не то
  • Пропускает интеграционные сценарии — только юнит-уровень

Best practices:

  • Целевые значения — 70-80% для критического кода, 100% для safety-critical систем
  • Фокус на сложных участках — бизнес-логика, условия, обработка ошибок
  • Комбинирование метрик — покрытие + статический анализ (SonarQube)
  • Отказ от гонки за процентами — важнее осмысленные тестовые сценарии

Ответ 18+ 🔞

А, тестовое покрытие! Ну это ж классика, блядь, вечная тема для споров на кухне, пока кто-нибудь не запустит тесты и не поймёт, что нихуя не покрыто.

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

Какие бывают уровни, от простого к мудёному:

  1. Покрытие строк — ну, тут всё просто, блядь. Строку кода выполнили — она покрыта. Не выполнили — не покрыта. Но это, ёпта, как считать голые стены за ремонт.
  2. Покрытие ветвей — вот это уже серьёзнее. Это про все эти if/else, switch. Проверил ты только одну сторону условия — и всё, пиши пропало, покрытие ветвей — 50%, хоть все строки и выполнились. Вот где собака, сука, зарыта чаще всего!
  3. Покрытие путей — это уже для мазохистов, блядь. Учитывает все возможные последовательности выполнения, все комбинации ветвлений. Овердохуища вариантов получается, покрыть это всё — жизни не хватит.
  4. Покрытие условий — когда внутри одного if у тебя (a > 0 && b.isValid()). Так вот, это метрика смотрит, проверял ли ты случай, когда первое условие true, а второе false, и наоборот. Короче, адский геморрой, но для ответственного кода — святое дело.

Вот, смотри, наглядный пиздёж на JavaScript:

// math.js
function divide(a, b) {
  if (b === 0) {          // Вот она, развилочка, блядь! Ветвь 1
    throw new Error('На ноль делить нельзя, мудак!');
  }
  return a / b;           // А это ветвь 2, счастливая
}

// math.test.js
test('divide throws on zero', () => {
  expect(() => divide(10, 0)).toThrow();  // О, мы молодцы! Проверили ветвь 1, где ошибка!
});
// А ветвь 2, где всё работает, мы, блядь, не проверили ни хуя! Итог: покрытие ветвей — 50%. Пиздец.

Чем меряют? Да чем угодно, инструментов — как говна за баней:

  • Java — JaCoCo, Cobertura (старички, но в теме)
  • Python — coverage.py (де-факто стандарт, блядь)
  • C# — Coverlet (модный, молодой)
  • Go — да там вообще встроенное, go test -cover, красота!

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

  • Самообман чистой воды. 100% покрытия — это не знак качества, это знак того, что кто-то хорошо умеет гонять тесты. Тест может проходить и при этом проверять полную хуйню.
  • Интеграцию не ловит. Всё это в основном про юниты, а как твои модули друг с другом общаться будут — покрытие молчит, как Герасим.
  • Качество != покрытие. Можно написать тест, который просто вызывает функцию и радуется, что не упал. Покрытие будет, а толку — ноль, ебать.

Так как же жить-то, спросишь?

  • Не гонись за соткой, как угорелый. Для обычного бизнес-кода 70-80% — уже охуенно. Для систем, где ошибка — катастрофа (типа управления реактором), да, там 100%, иначе никак.
  • Бей в самые больные места. Вся эта бизнес-логика, условия, обработка ошибок — вот где надо выкладываться. Геттеры-сеттеры сами как-нибудь покроются.
  • Одной метрикой сыт не будешь. Комбинируй, блядь! Покрытие + статический анализ (типа SonarQube) + ревью кода. Вот тогда картина будет.
  • Смысл важнее циферки. Лучше десять осмысленных тестов на важную логику, чем сто тупых, которые просто для галочки.

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