Java QA Antipatterns Catalog
Каталог антипаттернов автоматизированного функционального тестирования на Java.
Каждый модуль — самостоятельный проект, демонстрирующий один антипаттерн: проблемный код и его исправленную версию.
Требования
- Java 21
- Gradle 9+
- Google Chrome (для модулей с Selenium)
Сборка и запуск тестов
# Все модули
./gradlew test
# Конкретный модуль
./gradlew :test-interdependency:test
Примечание: два модуля содержат тест-классы с
@Disabled— они намеренно демонстрируют реальное падение из-за антипаттерна. Запустить вручную:./gradlew :no-data-isolation:test # NoDataIsolationAntipatternTest ./gradlew :interacting-tests:test # InteractingTestsAntipatternTest
Антипаттерны
| Модуль | Антипаттерн | Описание |
|---|---|---|
| fragile-locators | Хрупкие локаторы | Локаторы по автогенерированным id, позиции в DOM и CSS-классам фреймворка |
| hard-coded-sleeps | Жёсткие задержки |
Thread.sleep вместо явного ожидания условия |
| no-page-object | Нет Page Object | Selenium-вызовы разбросаны по тестам вместо инкапсуляции в Page Object |
| god-object-page-object | Разбухший Page Object | Один класс описывает весь сайт вместо отдельного класса на страницу |
| test-interdependency | Зависимые тесты | Тест молчаливо опирается на результат другого теста |
| hardcoded-data | Hardcoded данные | Пароли и цены вшиты в код вместо конфига и фабрик |
| assert-in-page-object | Assert в Page Object | Page Object делает проверки вместо возврата следующей страницы |
| assertion-roulette | Assertion Roulette | Множество независимых assert в одном тесте |
| empty-catch | Пустой catch | Исключение проглочено — тест зелёный, функциональность не проверена |
| sleep-chain | Цепочки sleep | Несколько Thread.sleep подряд после каждого действия |
| singleton-web-driver | Singleton WebDriver | Один статический WebDriver на всю JVM ломает параллельный запуск |
| data-clones | Дублирование данных | Одинаковые объекты создаются вручную в каждом тесте |
| white-box-testing | White-box Testing | Тест проверяет внутреннюю реализацию вместо поведения |
| excessive-xpath | Избыточный XPath | Сложные XPath-выражения вместо стабильных CSS-селекторов |
| no-data-isolation | Нет изоляции данных | Тест создаёт данные и не убирает их — загрязняет следующие тесты |
| mystery-guest | Mystery Guest | Тест зависит от файла или записи, созданных вне тест-метода |
| eager-test | Жадный тест | Один тест проверяет несколько независимых сценариев |
| general-fixture | Общая фикстура |
@BeforeEach создаёт объекты «на все случаи», большинство не используется |
| irrelevant-information | Посторонняя информация | Тест заполняет поля, не влияющие на проверяемое поведение |
| indirect-testing | Косвенное тестирование | Тест обращается к цели через фасад — непонятно, где именно сломалось |
| conditional-test-logic | Условная логика в тесте |
if/for в теле теста — непредсказуемое поведение и скрытые ошибки |
| interacting-tests | Взаимодействующие тесты | Тесты случайно влияют друг на друга через общее статическое состояние |
| context-sensitivity | Чувствительность к контексту | Тест зависит от системного времени, локали или переменных окружения |
| test-hook | Test Hook | Продакшн-код содержит ветки if (testMode) только для тестов |
| lonely-test | Одинокий тест | Тест проходит в сьюте, но падает при запуске в одиночку |