Логотип ConstructiCat
CodeBust.
Навигация по разделу ▾

Запахи тестов.

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

Маскот антипаттернов
Рулетка проверок

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

001
Маскот паттернов проектирования
Нетерпеливый тест

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

002
Маскот антипаттернов
Избыточная проверка

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

003
Маскот рефакторинга
Неизвестный тест

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

004
Маскот архитектурных паттернов
Дублирующаяся проверка

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

005
Маскот архитектурных паттернов
Чувствительное равенство

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

006
Маскот рефакторинга
Универсальная фикстура

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

007
Маскот антипаттернов
Таинственный гость

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

008
Маскот запахов кода
Ресурсный оптимизм

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

009
Маскот паттернов проектирования
Инициализация в конструкторе

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

010
Маскот рефакторинга
Невнятный тест

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

011
Маскот запахов кода
Условная логика в тесте

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

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

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

013
Маскот запахов кода
Тест с магическими числами

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

014
Маскот рефакторинга
Многословный тест

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

015
Маскот архитектурных паттернов
Неустойчивый (нестабильный, flaky) тест

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

016
Маскот антипаттернов
Спящий тест

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

017
Маскот рефакторинга
Война тестовых прогонов

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

018
Маскот запахов кода
Зависимость от порядка тестов

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

019