23 классических паттерна, разделенных на 3 категории:
1. Порождающие (Creational)
2. Структурные (Structural)
3. Поведенческие (Behavioral)
Гарантирует, что класс имеет только один экземпляр.
Применение в QA:
public class TestConfig {
private static TestConfig instance;
private Properties props;
private TestConfig() { loadProperties(); }
public static TestConfig getInstance() {
if (instance == null) {
instance = new TestConfig();
}
return instance;
}
}
Использование: Для хранения глобальной конфигурации тестов.
Определяет интерфейс для создания объекта, но оставляет подклассам решение о том, какой класс инстанцировать.
Пример:
public interface WebDriverFactory {
WebDriver createDriver();
}
public class ChromeDriverFactory implements WebDriverFactory {
public WebDriver createDriver() {
return new ChromeDriver();
}
}
Инкапсулирует работу с элементами страницы в отдельный класс.
Пример:
public class LoginPage {
private WebDriver driver;
public LoginPage(WebDriver driver) {
this.driver = driver;
}
public void login(String user, String pass) {
driver.findElement(By.id("username")).sendKeys(user);
driver.findElement(By.id("password")).sendKeys(pass);
driver.findElement(By.id("login-btn")).click();
}
}
Динамически добавляет объекту новые обязанности.
Применение:
public abstract class WebElementDecorator implements WebElement {
protected WebElement element;
public WebElementDecorator(WebElement element) {
this.element = element;
}
// Декорируем метод click
@Override
public void click() {
System.out.println("Clicking on element");
element.click();
}
}
Определяет зависимость "один-ко-многим" между объектами.
Пример в тестировании:
public class TestStatusNotifier {
private List<TestListener> listeners = new ArrayList<>();
public void addListener(TestListener listener) {
listeners.add(listener);
}
public void testFailed(String testName) {
for (TestListener l : listeners) {
l.onTestFailure(testName);
}
}
}
Определяет семейство алгоритмов, инкапсулирует каждый из них и делает их взаимозаменяемыми.
Применение:
public interface ScreenshotStrategy {
void takeScreenshot(WebDriver driver, String name);
}
public class FullPageScreenshot implements ScreenshotStrategy {
public void takeScreenshot(WebDriver driver, String name) {
// Реализация для полной страницы
}
}
Пошаговое создание сложного объекта.
Пример тестовых данных:
User user = new User.Builder()
.withUsername("testuser")
.withEmail("test@example.com")
.withActiveStatus(true)
.build();
Предоставляет объект-заместитель, контролирующий доступ к другому объекту.
Использование для логгирования:
public class LoggingWebElementProxy implements InvocationHandler {
private WebElement element;
public Object invoke(Object proxy, Method method, Object[] args) {
System.out.println("Calling: " + method.getName());
return method.invoke(element, args);
}
}
Наиболее полезные паттерны для QA:
Польза от знания паттернов:
Паттерны - это не догма, а инструменты для решения типовых задач проектирования ПО. В QA особенно важно понимать Page Object, Factory и Singleton как наиболее часто применяемые.