Ответ
Помимо Page Object Model (POM), в построении поддерживаемых и масштабируемых автотестов я активно применяю следующие паттерны:
1. Factory Method / Abstract Factory: Использую для создания экземпляров драйверов или сложных объектов данных. Это позволяет легко переключаться между браузерами или окружениями.
public class DriverFactory {
public static WebDriver createDriver(String browserName) {
switch (browserName.toLowerCase()) {
case "chrome":
WebDriverManager.chromedriver().setup();
return new ChromeDriver();
case "firefox":
WebDriverManager.firefoxdriver().setup();
return new FirefoxDriver();
case "remote":
return new RemoteWebDriver(new URL("http://grid-hub:4444"), new ChromeOptions());
default:
throw new IllegalArgumentException("Unsupported browser: " + browserName);
}
}
}
// Использование в тесте
WebDriver driver = DriverFactory.createDriver(System.getProperty("browser", "chrome"));
2. Singleton (с осторожностью):
Применяю для менеджеров, которые должны быть в единственном экземпляре, например, для управления драйвером в многопоточном окружении через ThreadLocal.
3. Builder: Идеален для создания сложных тестовых данных (пользователей, заказов) с множеством необязательных полей.
User testUser = new User.Builder()
.withUsername("test_user")
.withEmail("user@test.com")
.withActiveStatus(true)
.build();
// В тесте использую только нужные поля
loginPage.loginWithUser(testUser);
4. Strategy: Позволяет инкапсулировать алгоритмы проверок (стратегии валидации) и выбирать их во время выполнения. Например, разные стратегии проверки результатов поиска: по точному совпадению, по наличию ключевых слов, по фильтрации.
5. Facade:
Создаю упрощенный интерфейс для работы со сложными подсистемами. Например, ApiClientFacade скрывает детали настройки HTTP-клиента, аутентификации и парсинга ответов, предоставляя тесту простые методы getUser(), createOrder().
6. Data-Driven Testing (не строго GoF, но критически важный):
Отделяю тестовые данные от логики теста. Использую внешние источники (JSON, XML, Excel, БД) для параметризации тестов. В JUnit это @ParameterizedTest, в TestNG — @DataProvider.
7. Fluent Interface / Chain of Invocations: Делаю API page-объектов более читаемым.
// Вместо:
loginPage.enterUsername("user");
loginPage.enterPassword("pass");
loginPage.clickLogin();
// Использую:
loginPage
.enterUsername("user")
.enterPassword("pass")
.clickLogin();
Комбинация паттернов — ключ к успеху. Например, Page Object часто содержит элементы, инициализированные через @FindBy (шаблон Page Factory), а тестовые данные подаются в него через Builder, а сам тест является Data-Driven.