Полезное сквозное тестирование с Protractor
Часть 2
Тестируем список issues
От тестов работы элемента <input>
перейдём к тестам функционала нашего списка.
Поскольку все остальные тесты будут совершаться на странице списка, поместим их внутрь отдельного блока describe()
. Это позволит добавить ещё один блок с beforeEach()
. Для тестов возьмём репозиторий на гитхабе angular/angular.js
.
Блок describe()
будет вести себя, как пользователь, который заходит на главную страницу, заполняет поле ввода и жмёт enter. Вам может показаться излишним такой тест, но не забывайте, что сквозное тестирование и предполагает автоматизацию взаимодействия пользователя с системой.
|
|
На странице со списком issues
будет ряд элементов, которые мы будем перебирать с помощью ng-repeat
. Используя API GitHub, по умолчанию загрузим 30 issues. Соответственно, необходимо убедиться, что на странице реально появляется 30 вопросов.
Чтобы выбрать элемент в ng-repeat
, воспользуемся опцией by.repeater()
. Этот метод перебирает директивы ng-repeat
на странице и находит те, которые соответствуют заданному выражению. В данном случае мы задаём Angular выражение d in data | orderBy:created_at:false
.
Соответственно, запускаем цикл:
|
|
Можно как детально прописывать фильтры (что мы сделали выше), так и задать более общее выражение:
|
|
Метод by.repeater()
возвращает ссылку на метод, извлекающий элементы, а не сами элементы. Поэтому, если мы попытаемся проверить объект, возвращенный by.repeater(), мы получим ошибку. Protractor устроен таким образом потому что он использует promises для асинхронных операций, поэтому для работы с полученными объектами мы должны использовать функцию element.all()
:
|
|
Найдя элемент, чтобы подсчитать количество, применяем count()
к объекту element.all()
, и задаём ожидаемое количество — 30 элементов:
|
|
Отлично, копнём глубже и убедимся, что для каждого из повторяющихся элементов отображается аватар. Логично предположить, что каждый элемент это, по сути, повтор предыдущего, поэтому создадим тест и проверим лишь один элемент.
Для получения элементов со страницы воспользуемся уже знакомым методом by.repeater()
. Метод element.all()
возвращает объект, содержащий несколько методов, которые можем использовать для взаимодействия с повторяющимися элементами списка. В нашем случае, применим метод first()
для нахождения первого элемента списка.
Поскольку список ещё не появился на странице, метод first()
получает promise, который будет выполнен с появлением первого элемента.
|
|
Так как нам нужен конкретный дочерний элемент, применим метод findElement()
для нахождения элемента <img>
. Получить этот элемент можно разными методами, мы воспользуемся by.tagName()
. Как и в случае с методом first()
, метод findElement()
возвращает promise.
|
|
Нам важно, чтобы атрибут src содержал URL граватара. Поэтому протестируем ещё глубже структуру элемента. Применим метод getAttribute()
для нахождения атрибута src. Как и в двух предыдущих случаях, мы имеем дело с promises:
|
|
Получив атрибут src, зададим ожидание, что он соответствует gravatar.com
, поскольку на гитхабе используется именно Gravatar.
Тестируем навигацию
Последняя часть функционала, которую необходимо протестировать — навигация. Как и прежде, мы привяжем наши тесты к действиям, совершаемым на странице. В данном случае, протестируем ссылку /about
, используя CSS и click по ссылке.
Наш HTML выглядит следующим образом:
|
|
Ссылка /about
— второй элемент в списке header.nav
. Наиболее просто выбрать список с помощью селектора CSS и метода by.css()
.
|
|
Теперь у нас есть ссылка, на которую можно кликнуть, чтобы попасть на новую страницу. Переместившись на страницу /about
, следует убедиться, что содержание страницы отображается или что url содержит путь /about
. Поскольку мы подразумеваем, что Angular роутер работает как положено, очевидно, что страница будет грузиться, если url страницы ведёт на /about
. Поэтому просто проверяем последнее условие. Получим url с помощью метода getCurrentUrl()
:
|
|
Наконец, тк мы тестируем клиентский интерфейс, ожидаем, что к ссылке будет добавляться класс active
, который вешает на кнопку новый стиль color.
Запускаем то же действие, что и раньше — клик по ссылке /about
. Всякий раз, когда мы дублируем код, разумно вложить тесты в отдельный блок describe()
, и переместить туда дублируемый код. Переместим наши тесты в блок describe()
:
|
|
Последний тест проверяет, что список классов содержит строку active
:
|
|
Ещё аргументы?
Protractor – очень мощный инструмент для e2e тестирования, активно развивающийся на гитхабе. Вскоре он заменит Karma, став официальным фреймворком для Angular.
Исходный код тестов доступен по ссылке.
Спасибо за внимание, и продуктивного тестирования!