Полезное сквозное тестирование с 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.
Исходный код тестов доступен по ссылке.
Спасибо за внимание, и продуктивного тестирования!