---
title: "Игнорируемый тест"
type: "test-smell"
slug: "ignored-test"
url: "http://localhost:3000/ru/test-smells/ignored-test.md"
category: "Устранимые запахи"
description: "Тест, который закоммичен в кодовую базу, но никогда не выполняется, потому что он пропущен, отключён или закомментирован, создавая видимость покрытия, ничего на самом деле не проверяя."
---
# Игнорируемый тест

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

## Signs and Symptoms

Тест существует в наборе, но навсегда лишён возможности выполняться. Он по-прежнему считается «тестом» в файле, однако даёт ноль проверки. Высматривайте маркеры skip/ignore, блоки с префиксом `x`, пустые тела и код тестов, погребённый в комментариях, — нередко в паре с расплывчатой отговоркой вроде _«flaky»_ или _«fix later»_.

```js
// модификаторы skip/disabled — никогда не выполняются
describe.skip('checkout flow', () => { /* ... */ });
it.skip('applies the discount', () => { /* ... */ });
test.todo('handles expired coupons');

// с префиксом x (jasmine/jest/mocha) — тот же эффект
xit('rejects negative amounts', () => { /* ... */ });
xdescribe('payments', () => { /* ... */ });

// закомментированный тест — невидим И для раннера, И для репортёра
// it('retries on 503', async () => {
//   await expect(client.fetch()).resolves.toBeOk();
// });

```

```java
// JUnit: @Ignore / @Disabled с расплывчатой причиной
@Ignore("disabled for now as this test is too flaky")
@Test public void peerPriority() { /* ... */ }

```

Выдающие признаки в отчёте о тестах: ненулевой счётчик «skipped»/«pending», на который никто не смотрит; наборы, тихо съёжившиеся со временем; и пропуски без привязанной задачи или срока истечения. Условные `return` в начале теста (`if (process.platform === 'win32') return;`) — более хитрый вариант, полностью скрывающий пропуск от счётчиков пропусков.

## Reasons for the Problem

**Почему это происходит**

* Тест начал падать (настоящая регрессия, нестабильная зависимость от времени, смена среды/версии), и пропуск был самым быстрым способом получить зелёную сборку или разблокировать слияние.
* Тест был написан раньше реализации (`test.todo`/`xit` как заглушка) и к нему так и не вернулись.
* Миграции (новый фреймворк, среда выполнения или API) сломали тест, и его припарковали «временно».
* Пропуск задумывался на полдня; без напоминания, срока истечения или отслеживающей задачи он становится постоянным.

**Почему это вредно**

* **Ложная уверенность.** Пропущенный тест выглядит как покрытие в файле и в diff пул-реквеста, но ничего не проверяет. Путь кода, который он якобы защищал, теперь без охраны, а все считают его безопасным.
* **Гниение.** Игнорируемый тест никогда не компилируется (в некоторых языках), не рефакторится и не обновляется. Чем дольше он лежит, тем сильнее отходит от реальности, пока его повторное включение не станет дороже переписывания.
* **Скрытые регрессии.** Баг или нестабильное поведение, спровоцировавшее пропуск, всё ещё на месте — его просто заглушили. Пропуск лечит симптом (красную полосу), а не болезнь.
* **Шум и эрозия.** Постоянные счётчики «пропущено» приучают команду игнорировать отчёт о тестах, из-за чего _новые_ пропуски проскальзывают незамеченными. Мёртвый и закомментированный код тестов также добавляет издержки на чтение и сопровождение без всякой пользы.

## Treatment

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

1. **Разберите каждый пропуск.** Для каждого отключённого/закомментированного/`todo`\-теста решите: _починить_, _удалить_ или _поместить в карантин со сроком истечения и отслеживаемой задачей_. «Оставить пропущенным навсегда» — не вариант.
2. **Почините и снова включите,** если поведение всё ещё важно. Если тест нестабилен, устраните нестабильность (возьмите под контроль время, случайность, асинхронность и общее состояние), а не пропускайте его.
3. **Удалите его,** если функциональность исчезла или тест устарел. Удалённый тест честен; пропущенный лжёт. Система контроля версий помнит его, если он когда-нибудь понадобится, — поэтому никогда не _комментируйте_ тест вместо его удаления.
4. **Если приходится пропустить временно, сделайте это громко и с ограничением по времени:** всегда указывайте причину и ссылку на отслеживание, и предпочитайте механизм, который проявляется в отчётах и падает по истечении срока, чтобы пропуск не сгнил.
5. **Остановите кровотечение с помощью линтера/CI.** Включите правило «никаких отключённых тестов», чтобы новые пропуски ловились на ревью, и относитесь к существующему счётчику пропусков как к бэклогу, который нужно свести к нулю.

```js
// до — тихо, навсегда, без отслеживания
it.skip('refunds the full amount on cancel', async () => {
  await expect(refund(order)).resolves.toEqual({ amount: 100 });
});

// после — починен и снова работает (коренная причина: итог с плавающей точкой)
it('refunds the full amount on cancel', async () => {
  await expect(refund(order)).resolves.toEqual({ amount: 100 });
});

// допустимый промежуточный вариант — заметный, с указанием автора и сроком истечения
it.skip('refunds the full amount on cancel — flaky clock, see JIRA-1234 (remove by 2026-07-01)', async () => {
  /* ... */
});

```

```java
// до
@Ignore("too flaky")
@Test public void peerPriority() { ... }

// после: почините зависимость от тайминга и снова включите, или удалите, если устарел
@Test public void peerPriority() { ... }

```

## Detected by

- **eslint-jest** `jest/no-disabled-tests` — Запретить отключённые тесты (https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/no-disabled-tests.md)
- **eslint-jest** `jest/no-commented-out-tests` — Запретить закомментированные тесты (https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/no-commented-out-tests.md)
- **eslint-vitest** `vitest/no-disabled-tests` — Запретить отключённые тесты (https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/no-disabled-tests.md)
- **eslint-vitest** `vitest/no-commented-out-tests` — Запретить закомментированные тесты (https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/no-commented-out-tests.md)
- **sonar** `java:S1607` — Тесты не должны игнорироваться (https://rules.sonarsource.com/java/RSPEC-1607/)
- **sonar** `javascript:S1607` — Тесты не должны пропускаться без указания причины (https://rules.sonarsource.com/javascript/RSPEC-1607/)
