Паттерн Traits | OTUS
⚡ Подписка на курсы OTUS!
Интенсивная прокачка навыков для IT-специалистов!
Подробнее

Курсы

Программирование
Алгоритмы и структуры данных Team Lead Архитектура и шаблоны проектирования Разработчик IoT C# Developer. Professional PostgreSQL Разработчик на Spring Framework
-5%
Flutter Mobile Developer NoSQL iOS Developer. Basic
-10%
C++ Developer. Basic C++ Developer. Professional Android Developer. Professional Microservice Architecture Unity Game Developer. Professional Базы данных Node.js Developer React.js Developer Специализация Java-разработчик
-25%
Web-разработчик на Python Framework Laravel Cloud Solution Architecture Vue.js разработчик Интенсив «Оптимизация в Java» Супер - интенсив по паттернам проектирования Супер - интенсив по Kubernetes Супер-интенсив "Tarantool" PHP Developer. Basic
Инфраструктура
Мониторинг и логирование: Zabbix, Prometheus, ELK Administrator Linux. Professional Дизайн сетей ЦОД Разработчик IoT PostgreSQL Экспресс-курс "Версионирование и командная работа с помощью Git"
-30%
Microservice Architecture Highload Architect Специализация Administrator Linux
-25%
Network engineer Cloud Solution Architecture Внедрение и работа в DevSecOps Супер-практикум по работе с протоколом BGP Супер - интенсив по паттернам проектирования Супер - интенсив по Kubernetes Супер-интенсив «СУБД в высоконагруженных системах» Супер-интенсив "Tarantool" Network engineer. Basic
Корпоративные курсы
Безопасность веб-приложений IT-Recruiter Дизайн сетей ЦОД Компьютерное зрение Разработчик IoT Вебинар CERTIPORT Machine Learning. Professional
-6%
NoSQL Пентест. Практика тестирования на проникновение Java QA Engineer. Базовый курс Руководитель поддержки пользователей в IT
-8%
SRE практики и инструменты Cloud Solution Architecture Внедрение и работа в DevSecOps Супер-практикум по работе с протоколом BGP Infrastructure as a code Супер-практикум по использованию и настройке GIT Промышленный ML на больших данных Экспресс-курс «CI/CD или Непрерывная поставка с Docker и Kubernetes» BPMN: Моделирование бизнес-процессов Основы Windows Server
Специализации Курсы в разработке Подготовительные курсы Подписка
+7 499 938-92-02

Паттерн Traits

Сложно переоценить важность паттернов. Они помогают писать код более структурировано, тратить меньше времени на отладку кода, позволяют новым людям в команде быстрее и проще влиться в процесс.

Как в разработке, так и в тестировании есть свои паттерны. И, безусловно, самым популярным и востребованным паттерном разработки автотестов является паттерн Page Object.

Page Object (далее PO) — паттерн проектирования автотестов, когда логика (методы, функции) отделены от самих тестов.

Данный паттерн позволяет более эффективно писать код, вызывая в тесте нужные нам методы:

productPage
        .clickDeliveryBtn()
        .clickCheckoutBtn();

Этот паттерн хорошо себя показывает ровно до момента, пока вы не попадаете на проект, где реализована технология SPA (Single Page Application).

Представим себе типичный интернет-магазин. На каждой странице есть подвал (далее footer) и шапка (далее header). В Header'е и в footer'е есть поле ввода текста (поиск).

Как нам в данном случае поступить? Использовать классический PO, описывая на каждой странице и footer, и header? Это будет нарушением принципа DRY (Don't Repeat Yourself), к тому же, при изменении одного из элементов (к примеру, в header был добавлен новый элемент) придется ходить по всем страницам и изменять в каждом классе.

Использовать некий, промежуточный класс? Тогда в некоторых классах, описывающих страницы, будут «лишние» методы. К примеру, на подробном описании страницы есть только footer, в корзине есть только header. Если у нас будет один общий класс, где описан header и footer, то на страницах подробного описания у нас будут методы для footer'a, что будет мешать в разработке (и может привести к некорректному поведению тестов).

Сделать несколько классов, где будут вариации наследования? Опять же, нарушение принципов DRY(а так же SOLID), а сколько будет вариаций при, скажем, 4 вариантов header'a и footer'a страшно представить.

На помощь нам приходит дальнейшая эволюция PO в виде WO (Widget Object), ScreenPlay, но, по моему мнению, они не удобны.

WO не удобен с точки зрения восприятия (если использовать «чистый» WO). Вот у нас не отработал виджет поиска. На какой странице это случилось? Как понять?

Использовать смешанное решение в виде PO + WO? Встает снова вопрос с наследованием. Как нам наследоваться от нескольких виджетов? Создать на каждой странице/тесте n виджетов? Опять же, нарушение DRY со всеми вытекающими.

Использовать паттерн ScreenPlay? Не все используют Cucumber/Serenity.

Паттерн Traits

Начиная с Java 8, в интерфейсах ради сохранения обратной совместимости был добавлен модификатор default. Данный модификатор позволяет в интерфейсе реализовать метод по умолчанию. Это и позволит нам реализовать паттерн Traits, ведь множественное наследование интерфейсов в Java не запрещено.

Паттерн Traits используется в объектно-ориентированном программировании, который представляет собой набор методов, которые могут быть использованы, чтобы расширить функциональные возможности класса.

Или, простыми словами, для каждого теста мы «собираем» свои методы, которые нам нужны для конкретного теста. Нам нужен header? Подключаем интерфейс с методами для header'a. Нам еще нужны методы для главной страницы? Нет ничего проще, подключаем интерфейс MainPage.

Простой пример использования данного паттерна. Создадим простейший интерфейс, который будет выводить нам текст "Here you trait!"

public interface Trait {
    default Trait giveMeTrait(){
        System.out.println("Here you trait!");
        return this;
    }
}

И имплементируем его в наш класс:

public class MyTraitClass implements Trait{
    @Test
    void testTrait(){
        giveMeTrait();
    }
}

Готово. Таким образом мы можем подключить только нужные trait в тест, избавившись от ненужных в данном тесте методов.

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

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

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

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