Курсы

Курсы в разработке Подготовительные курсы
Работа в компаниях Компаниям Блог +7 499 110-61-65

Паттерны для тестировщиков: proxy

JQA_Deep_8.5_site-5020-614a43.png

Главная идея паттерна proxy (в русскоязычных изданиях его называют «заместитель») состоит в том, чтобы выдать для работы не реальный объект, а подмену, которая использует методы объекта и нашу логику, если мы такую добавили.

Как это делается

1) Создаём интерфейс с публичными методами объекта, который хотим подменить. 2) Создаём класс, который: — реализует этот интерфейс; — имеет доступ к оригинальному объекту, чтобы вызывать его методы. 3) Добавляем в методы созданного класса свою логику.

Практика

На практике должно быть понятней. Дано: есть у нас WebDriver. И есть у него метод findElements(By by); Задача: мне очень сильно нужно логировать, сколько элементов было найдено по селектору.

Каждый раз, когда я вызываю метод:

driver.findElements(By.cssSelector(".item"));

я хочу видеть в логах запись — сколько элементов было найдено.

Решение 1. В лоб

Чего уж там: я его применял. Просто берём и при каждом вызове пишем, сколько было найдено:

List<WebElement> items = driver.findElements(By.cssSelector(".item"));
logger.info("Found {} items", items.size());

Вариант нормальный, пока таких вызовов, ну, скажем, 7. Хотя уже неприятно и минусы такого подхода очевидны любому, кто хоть раз «слегка модифицировал свой код».

Решение 2. Используем прокси

WebDriver — интерфейс. Объявлены методы, но нет реализации. Реализацию содержат ChromeWebDriver, FirefoxWebDriver и т. д. Нам, в тестах, не обязательно работать с каким-то конкретным классом для хрома или сафари. Нужно только, чтобы класс имплементил интерфейс WebDriver. Это и сделаем.

Создаём интерфейс с публичными методами объекта, который хотим подменить. В нашем примере такой интерфейс уже есть — WebDriver. Создаём класс, который: — реализует этот интерфейс; — имеет доступ к оригинальному объекту, чтобы вызывать его методы.

public class LoggerWebDriver implements WebDriver{
    private WebDriver driver;

    public void get(String s) {     
    }

    public List<WebElement> findElements(By by) {
        return null;
    }

    public WebElement findElement(By by) {
        return null;
    }
//остальные методы отрезал для краткости
}

Добавляем в методы созданного класса свою логику:

public class LoggerWebDriver implements WebDriver {
    private WebDriver driver;
    private final Logger logger = LogManager.getLogger(LoggerWebDriver.class);

    LoggerWebDriver() {
        //жёстких ограничений по конструктору нет. 
        //В идеале, он(и) должны повторять конструкторы объекта.
        this.driver = new ChromeDriver();
    }

    public void get(String var1) {
        driver.get(var1);
    }

    public List<WebElement> findElements(By var1) {
        List<WebElement> items = driver.findElements(var1);
        logger.info("Selector {}. Found {} elements", var1.toString(), items.size());
        return items;
    }

    public WebElement findElement(By var1) {
        return driver.findElement(var1);
    }
//остальные методы отрезал для краткости
}

Что произошло?

В класс добавлен:

private WebDriver driver;

Это тот самый объект, который мы хотим подменить. Именно его методы мы будем вызывать дальше. Теперь, можно посмотреть, например, на метод:

public void get(String var1) {
      driver.get(var1);
}

Всё, что делает метод, — вызывает get() у настоящего драйвера. А вот метод:

public List<WebElement> findElements(By var1) {
      List<WebElement> items = driver.findElements(var1);
      logger.info("Selector {}. Found {} elements", var1.toString(), items.size());
      return items;
}

Мы расширили в соответствии с нашей задачей. Вот и всё, можно юзать в тестах:

WebDriver driver = new LoggerWebDriver();
driver.get("http://google.com");
List<WebElement> items = driver.findElements(By.cssSelector("a"));
// => Selector By.cssSelector: a. Found 48 elements

Паттерн хорош, если нужно навесить логирование, кэширование, ленивую инициализацию, контроль доступа к методам. В общем, если вы пишете код и вам очень хочется, чтобы была какая-то прослоечка с вашими фичами, один из вариантов — прокси.

Теперь, когда мы знаем на один паттерн больше, напомню, что когда в руке молоток, всё вокруг кажется гвоздями. Просто помните об этом.

Не пропустите новые полезные статьи!

Спасибо за подписку!

Мы отправили вам письмо для подтверждения вашего email.
С уважением, OTUS!

Автор
0 комментариев
Для комментирования необходимо авторизоваться