Применяли ли вы Generics (дженерики) в тестировании на Java?

«Применяли ли вы Generics (дженерики) в тестировании на Java?» — вопрос из категории Java, который задают на 24% собеседований AQA / Automation. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Да, активно использую дженерики для создания переиспользуемых, типобезопасных утилит и вспомогательных классов в автотестах. Это помогает избежать приведения типов (casting) и ошибок на этапе компиляции.

Пример 1: Универсальный билдер для тестовых данных

public class TestDataBuilder<T> {
    private T entity;
    private Consumer<T>[] modifiers;

    @SafeVarargs
    public TestDataBuilder(T baseEntity, Consumer<T>... modifiers) {
        this.entity = baseEntity;
        this.modifiers = modifiers;
    }

    public T build() {
        for (Consumer<T> modifier : modifiers) {
            modifier.accept(entity);
        }
        return entity;
    }

    // Использование для создания тестового пользователя
    public static void main(String[] args) {
        User testUser = new TestDataBuilder<>(
            new User(),
            u -> u.setName("QA_User"),
            u -> u.setEmail("test@qa.example.com"),
            u -> u.setActive(true)
        ).build();
        // `testUser` имеет конкретный тип User, а не Object
    }
}

Пример 2: Абстрактный класс для типобезопасных Page Object в Selenium

public abstract class BasePage<T extends BasePage<T>> {
    protected WebDriver driver;

    protected BasePage(WebDriver driver) {
        this.driver = driver;
    }

    // Метод, возвращающий конкретный тип страницы для цепочки вызовов
    public T and() {
        return (T) this;
    }

    public abstract T isPageOpened();
}

public class LoginPage extends BasePage<LoginPage> {
    private By usernameField = By.id("username");

    public LoginPage(WebDriver driver) {
        super(driver);
    }

    public LoginPage enterUsername(String user) {
        driver.findElement(usernameField).sendKeys(user);
        return this; // Возвращает LoginPage, а не BasePage
    }

    @Override
    public LoginPage isPageOpened() {
        // Реализация проверки
        return this;
    }
}
// Использование: new LoginPage(driver).isPageOpened().enterUsername("test").and()...

Преимущества в QA:

  • Безопасность: Компилятор проверяет типы в коллекциях (например, List<WebElement>) и наших утилитах.
  • Переиспользование: Можно писать общие методы для работы с разными типами сущностей (пользователи, заказы, товары).
  • Читаемость: Код тестов становится чище, исчезают предупреждения unchecked cast.