Приведи пример применения паттерна Factory
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Пример применения паттерна Factory в автоматизации тестирования
Паттерн Factory (Фабрика) — это порождающий шаблон проектирования, который предоставляет интерфейс для создания объектов в суперклассе, позволяя подклассам изменять тип создаваемых объектов. В контексте QA и автоматизации тестирования он особенно полезен для создания сложных, зависимых или конфигурируемых объектов, таких как драйверы браузеров, клиенты API, тестовые данные или page objects.
Проблема без использования Factory
Представьте, что вам нужно протестировать веб-приложение в разных браузерах (Chrome, Firefox). Код без паттерна может выглядеть так, с условными операторами, разбросанными по всему тестовому коду:
// ПЛОХОЙ ПРИМЕР: Жёсткая привязка и дублирование кода
public class LoginTest {
WebDriver driver;
@BeforeTest
public void setup() {
String browser = System.getProperty("browser"); // Получаем из конфигурации
if (browser.equals("chrome")) {
WebDriverManager.chromedriver().setup();
driver = new ChromeDriver();
} else if (browser.equals("firefox")) {
WebDriverManager.firefoxdriver().setup();
driver = new FirefoxDriver();
} else {
throw new IllegalArgumentException("Unknown browser");
}
}
@Test
public void testLogin() {
driver.get("https://example.com/login");
// ... шаги теста
}
}
Недостатки такого подхода:
- Нарушение принципа единственной ответственности (Single Responsibility Principle) — класс теста занимается и логикой теста, и созданием драйвера.
- Сложность расширения: Добавление нового браузера (например, Edge) потребует модификации всех тестовых классов.
- Дублирование кода: Каждый новый тестовый класс будет содержать одинаковый блок
if-else. - Сложность поддержки: Изменение логики инициализации (например, добавление опций) нужно вносить во множество мест.
Решение с помощью паттерна Factory
Мы инкапсулируем логику создания объекта в отдельный класс — Фабрику.
Шаг 1: Определяем интерфейс или абстрактный тип
Хотя в этом примере мы создаём конкретные объекты WebDriver, фабрика абстрагирует процесс их создания.
Шаг 2: Создаём фабричный класс
// ХОРОШИЙ ПРИМЕР: Класс-фабрика для создания WebDriver
public class WebDriverFactory {
public static WebDriver createDriver() {
// Читаем конфигурацию из одного места (property файла, системы, etc.)
String browser = ConfigManager.getProperty("browser").toLowerCase();
boolean headless = Boolean.parseBoolean(ConfigManager.getProperty("headless"));
WebDriver driver;
switch (browser) {
case "chrome":
WebDriverManager.chromedriver().setup();
ChromeOptions chromeOptions = new ChromeOptions();
if (headless) chromeOptions.addArguments("--headless=new");
driver = new ChromeDriver(chromeOptions);
break;
case "firefox":
WebDriverManager.firefoxdriver().setup();
FirefoxOptions firefoxOptions = new FirefoxOptions();
if (headless) firefoxOptions.addArguments("--headless");
driver = new FirefoxDriver(firefoxOptions);
break;
case "edge":
WebDriverManager.edgedriver().setup();
driver = new EdgeDriver();
break;
default:
throw new IllegalArgumentException("Unsupported browser: " + browser);
}
// Единое место для общих настроек
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
driver.manage().window().maximize();
return driver;
}
}
Шаг 3: Используем фабрику в тестах
// Тестовый класс теперь чистый и сфокусированный на логике теста
public class LoginTestWithFactory {
WebDriver driver;
@BeforeTest
public void setup() {
// Вся сложность создания спрятана за простым вызовом фабричного метода
driver = WebDriverFactory.createDriver();
}
@Test
public void testLogin() {
driver.get("https://example.com/login");
LoginPage loginPage = new LoginPage(driver);
loginPage.login("standard_user", "secret_sauce");
// ... проверки
}
@AfterTest
public void teardown() {
if (driver != null) {
driver.quit();
}
}
}
Ключевые преимущества для QA-инженера
- Централизованное управление: Вся логика создания и конфигурации WebDriver находится в одном месте (
WebDriverFactory). Чтобы добавить поддержку нового браузера или изменить timeout, нужно отредактировать только фабрику. - Упрощение тестовых классов: Тесты становятся короче, чище и сосредоточены исключительно на бизнес-логике и проверках, а не на инфраструктурном коде.
- Повышение переиспользуемости и поддерживаемости: Фабрику можно использовать в любом тестовом классе проекта. Это снижает дублирование кода и упрощает его поддержку.
- Гибкость конфигурации: Легко управлять поведением через внешние конфигурационные файлы. Например, можно запускать одну сборку в Chrome на локальной машине, а другую — в headless Firefox на CI-pipeline, не меняя код тестов.
- Следование принципам SOLID:
* **S**: Фабрика отвечает только за создание драйвера, тест — только за выполнение шагов.
* **O**: Система открыта для расширения (добавления новых браузеров) и закрыта для модификации существующих тестов.
Другие сценарии применения в тестировании
Паттерн Factory можно применять не только для драйверов:
- Фабрика тестовых данных: Создание сложных объектов данных (пользователей, заказов) с предзаполненными валидными, невалидными или граничными значениями.
User testUser = UserFactory.createValidAdminUser(); User invalidUser = UserFactory.createUserWithExpiredPassword(); - Фабрика клиентов API: Создание REST-клиентов с разными уровнями логирования, таймаутами или заголовками авторизации.
- Фабрика Page Objects: Инициализация page objects с инжекцией уже созданного драйвера.
Таким образом, паттерн Factory является мощным инструментом в арсенале QA-инженера, занимающегося автоматизацией. Он помогает строить стабильные, гибкие и легко поддерживаемые тестовые фреймворки, отделяя инфраструктурную сложность от тестовой логики, что в долгосрочной перспективе значительно сокращает затраты на поддержку автотестов.