ConstructiCat Logo
CodeBust.
Browse section ▾

Test Smells.

Recurring problems in test code — how to recognize each one, why it hurts, how to fix it, and the lint rules that detect it.

Antipatterns Mascot
Рулетка проверок

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

001
Design Patterns Mascot
Нетерпеливый тест

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

002
Antipatterns Mascot
Избыточная проверка

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

003
Refactoring Mascot
Неизвестный тест

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

004
Architectural Patterns Mascot
Дублирующаяся проверка

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

005
Architectural Patterns Mascot
Чувствительное равенство

Тест проверяет поведение, сравнивая строковое представление объекта (toString(), JSON.stringify(), отрендеренный HTML) с ожидаемым строковым литералом, тем самым привязываясь к несущественным деталям форматирования вместо действительно важных значений.

006
Refactoring Mascot
Универсальная фикстура

Общая подготовка строит одну большую фикстуру «на все случаи жизни», покрывающую потребности всех тестов, но каждый отдельный тест задействует лишь небольшую её часть.

007
Antipatterns Mascot
Таинственный гость

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

008
Code Smells Mascot
Ресурсный оптимизм

Ресурсный оптимизм — это когда тест предполагает, что внешний ресурс (файл, каталог, таблица БД, переменная окружения или сетевой эндпоинт) уже существует и находится в известном состоянии, вместо того чтобы создать и проверить его, из-за чего тест проходит или падает недетерминированно.

009
Design Patterns Mascot
Инициализация в конструкторе

Тестовый класс инициализирует поля фикстуры в конструкторе вместо специального хука подготовки фреймворка (setUp / @BeforeEach / TestInitialize), обходя жизненный цикл теста.

010
Refactoring Mascot
Невнятный тест

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

011
Code Smells Mascot
Условная логика в тесте

Тест, который использует `if`/`switch`/тернарные операторы, циклы или `try`/`catch`, чтобы решать, что выполнять или проверять, так что его поведение — и проверяет ли он что-либо вообще — зависит от того, какая ветка выполнится во время работы.

012
Refactoring Mascot
Дублирование тестового кода

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

013
Code Smells Mascot
Тест с магическими числами

Тест жёстко прописывает необъяснённые числовые литералы во входных данных и проверках, скрывая, что эти числа означают и откуда они взялись.

014
Refactoring Mascot
Многословный тест

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

015
Architectural Patterns Mascot
Неустойчивый (нестабильный, flaky) тест

Неустойчивый (flaky) тест на неизменном коде то проходит, то падает, потому что его исход зависит от тайминга, порядка выполнения, общего состояния или иных недетерминированных факторов, а не от проверяемого поведения.

016
Antipatterns Mascot
Спящий тест

Спящий тест приостанавливает выполнение захардкоженной задержкой (`Thread.sleep`, `setTimeout`, `cy.wait(2000)`, `page.waitForTimeout`), чтобы дождаться асинхронной работы, вместо того чтобы ждать само нужное условие.

017
Refactoring Mascot
Война тестовых прогонов

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

018
Code Smells Mascot
Зависимость от порядка тестов

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

019