Сегодня я расскажу вам небольшой трюк, как сделать ваш тестовый код немного интереснее и проще в сопровождении. Шаблон PageObject довольно распространен в мире тестирования Selenium, но он также может быть полезен, когда вы пишете модульные тесты для каждого отдельного UI-компонента.

Отказ от ответственности: не будет новой библиотеки, которую вам нужно будет установить перед началом работы. Эта статья о шаблоне кода. Вы можете использовать его с любым технологическим стеком, React используется здесь только для примера, но это не обязательно.
Но есть репозиторий Github с примерами из этой статьи, который вы можете добавить в закладки для дальнейшего использования.

Например, у нас есть компонент LoginForm, который предоставляет простой интерфейс для авторизации. Для простоты оставим в стороне логику обработки состояния, здесь будет компонент без состояния:

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

Затем нам нужно протестировать еще один вариант использования. Давайте добавим еще один тест и проведем его рефакторинг, переместив дублированный код во вспомогательную функцию:

Но мы все еще не могли избавиться от кода, который находит нам поля формы. У нас много похожих вызовов component.find(...)call, которые также следует заменить на помощник. В голове у меня возникла идея переместить строки селекторов в константы, чтобы сделать их многоразовыми. Но component.find(EMAIL_FIELD) выглядит не намного лучше, чем раньше. Здесь может быть лучший способ организовать все селекторы элементов, вы можете создать PageObject.

По сути, PageObject - это просто обычный объект, который дает вам доступ ко всей важной части страницы. Мы не тестируем всю веб-страницу, только один компонент, но мы можем думать, что наш компонент на самом деле является маленькой страницей, с которой мы собираемся взаимодействовать. В Javascript вы можете описать свою страницу так:

Теперь у нас есть единое место для описания нашего компонента и всех интерактивных элементов внутри. Каждый раз, когда внутренняя структура компонента будет меняться, нам нужно обновлять только эти аксессоры, весь остальной код, который их использует, может быть неизменным. Возможно, другие разработчики, которые позже будут поддерживать ваши тесты, поблагодарят вас за этого помощника.

Обратите внимание, что мы создали formField геттер, который принимает параметр. Вы можете найти это неприемлемым для вас, в качестве альтернативы вы можете создать специальные методы для каждого элемента, например emailField() и passwordField(), это тоже нормально и зависит от вас.

Давайте соберем все вместе и обновим наш набор тестов:

В настоящее время наш тестовый код поощряет делать все через объект Page. Это можно считать хорошей практикой, потому что каждый раз, когда вы собираетесь сделать что-то новое, вам нужно определить средство доступа, которое может быть повторно использовано позже. С другой стороны, вы всегда можете проверить, что может делать компонент, посмотрев определение объекта Page.

Наконец, давайте добавим еще один тест на обработку отправки. Мы можем не только использовать объект страницы для чтения данных, но и имитировать поведение пользователя в компоненте:

Вот и все. Оболочка объекта страницы дает вам удобный API для взаимодействия с вашим компонентом, поэтому тестовый код будет более выразительным и аккуратным. И это не требует от вас стольких усилий, просто следуйте этой простой схеме.

Однако здесь мы использовали React, это не обязательно. Вы можете использовать этот шаблон практически со всеми фреймворками, имеющими концепцию UI-Component. Фактическая реализация метода component.find() будет другим, но общий подход с объектом Page будет таким же.

Вот репозиторий Github, содержащий код из этой статьи и другие примеры. Я собираюсь сохранить его и добавить больше примеров для более сложных случаев. Не стесняйтесь задавать любые вопросы и отправлять запросы на включение!

Надеюсь, этот паттерн поможет вам протестировать ваши компоненты. Конечно, здесь есть еще несколько вещей, которые также могут вам помочь - настраиваемые сопоставители, построители данных - но это уже другая история. Удачного кодирования и следите за обновлениями!