Убедитесь, что ваше приложение выглядит так, как должно

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

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

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

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

Пример приложения React

Шаги, описанные в этом руководстве, должны работать в приложении, написанном на любой платформе. Мы будем использовать приложение React, которое показывает простую гистограмму, созданную с помощью Highcharts. Идите и клонируйте этот репозиторий Git.



Если вы хотите увидеть окончательный код после выполнения этого руководства, вы можете проверить ветку final этого репозитория Git.

Запустите npm start, чтобы запустить приложение.

Диаграмма содержит жестко запрограммированные значения для серии диаграмм. В реальном проекте он будет получен из серверной части API. Мы будем использовать визуальное тестирование, чтобы убедиться, что наша диаграмма выглядит именно так, когда пользователь ее видит.

Установка Cypress

После клонирования примера репозитория приложения React из Github перейдите в его корневую папку в своем терминале и установите Cypress.

npm install cypress --save-dev

Создайте сценарий npm для запуска cypress. В вашем package.json файле найдите раздел scripts и добавьте новую запись.

"scripts": {
    "cypress:open": "cypress open",
    ...
},

Теперь мы можем открыть Cypress Test Runner, выполнив эту команду:

npm run cypress:open

Откроется программа запуска тестов Cypress, и она предложит создать несколько примеров тестов, чтобы вы начали. Нажмите "ОК, понятно!" кнопка.

В корне вашего проекта будет создана папка cypress, а также файл cypress.json.

В разделе cypress/integration/examples вы увидите несколько примеров тестов, которые могут служить полезными справочными материалами. Я удалил их в этом уроке, чтобы убрать беспорядок.

Установка Cypress Image Snapshot Plugin

Cypress имеет различные команды, которые мы можем использовать для поиска определенных элементов, проверки их свойств, взаимодействия с браузером и имитации сетевых запросов. Однако в нем нет команды, которая бы "из коробки" поддерживала визуальное тестирование. К счастью, cypress можно расширить с помощью плагинов. Один конкретный плагин, который мы будем использовать, - это cypress-image-snapshot.

Давайте установим этот плагин с помощью этой команды:

npm install cypress-image-snapshot --save-dev

После установки пакета нам необходимо зарегистрировать плагин в Cypress. Откройте файл cypress/plugins/index.js и замените его содержимое следующим кодом:

Файл экспортирует функцию, которая имеет два параметра для прослушивания событий и конфигурацию проекта. Мы вызываем метод addMatchImageSnapshotPlugin, передавая два параметра.

Регистрации плагина недостаточно, так как он только подготовит плагин к прослушиванию различных событий кипариса для выполнения своих функций. Эти события будут вызывать команда Cypress.

Плагин cypress-image-snapshot имеет собственную команду для вызова событий, которые прослушиваются плагином. Это matchImageSnapshot, который мы будем использовать в наших кипарисовых тестах для захвата определенного элемента пользовательского интерфейса и сопоставления его с существующим снимком состояния. Нам нужно зарегистрировать эту команду, открыв файл cypress/support/commands.js и заменив его содержимое следующим:

После сохранения всех изменений мы готовы написать тест Cypress.

Написание теста

Создайте новый файл javascript в папке cypress/integration. Кипарисовый тест выглядит следующим образом:

Строка 1 отключает правило no-undef ESLint, так как включение его для этого файла помечает переменную cy ошибкой, поскольку она не была определена, но строка 2 фактически ссылается на типы Cypress, включая глобальную переменную cy. Если вы не используете ESLint, вы можете удалить эту строку.

Строка 4 вызывает функцию describe, которая является просто способом сгруппировать связанные тесты. Несмотря на то, что у нас есть только один тест, нам все равно нужно заключить его в функцию describe.

Строка 5 - это собственно тест. Мы вызываем функцию it, которая будет содержать команды для выполнения (в качестве альтернативы вы можете использовать точно такую ​​же тестовую функцию). Вы указываете описание для первого параметра, а второй параметр - это функция обратного вызова, содержащая основную часть теста.

Строка 6 вызывает команду visit для перехода в браузере к URL-адресу нашего приложения для тестирования. В строке 7 используется команда get для поиска элемента диаграммы. Если вы посмотрите на разметку элемента React, представляющего гистограмму, вы увидите, что я прикрепил класс в div, который включает фактическую диаграмму:

Поэтому я использовал .bar-chart в качестве селектора, переданного команде get.

Как только эта команда выбрана с помощью get, я привязал вызов к matchImageSnapshot.

cy.get('.bar-chart').matchImageSnapshot('barChart');

Помните, что мы зарегистрировали эту команду, которую предлагал плагин cypress-image-snapshot. Первый параметр - это имя снимка. Вы будете обращаться к этому имени при поиске снимка.

Команда делает следующее:

  1. Он делает снимок / снимок экрана выбранного элемента, в данном случае нашей гистограммы.
  2. Если изображение делается впервые, Cypress будет рассматривать его как снимок базового изображения. Команда будет выполнена автоматически, поскольку сравнивать не с чем.
  3. Если это не первый раз и в папке снимков уже есть базовое изображение, то будет выполнено попиксельное сравнение последнего снимка и базового снимка. Команда завершится ошибкой, если есть различия в пикселях базового изображения.

Запуск теста

Убедитесь, что приложение, которое вы будете тестировать, запущено и работает. В Cypress Test Runner щелкните только что созданный тестовый файл. Обратите внимание, что вы также можете выбрать браузер для запуска теста в правом верхнем углу.

Это откроет Chrome или выбранный вами браузер и выполнит тестовые команды.

Все тесты проходят успешно, особенно задача в строке 3, которая представляет команду matchImageSnapshot.

Это первый раз, когда мы запускаем команду, поэтому создается снимок и помечается команда как пройденная. Если вы посмотрите файл своего проекта, вы увидите, что создана snapshot папка.

Папка snapshots содержит подпапку для каждого запускаемого вами тестового файла. Внутри подпапки находится фактический снимок. Если вы откроете файл изображения, он покажет, как выглядит гистограмма в то время, которое мы назвали matchImageSnapshot.

Когда снимки не совпадают

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

Давайте сымитируем неудачный тест, просто изменив данные, которые используются на нашей гистограмме. Откройте src/BarChart.tsx файл. Найдите этот блок кода:

data: [
    ['John', 40],
    ['Mike', 24],
    ['Charles', 10],
    ['Susan', 5],
    ['Rebecca', 56],
],

Каждый подмассив представляет оси X и Y гистограммы. Идите вперед и измените некоторые числовые значения, чтобы повлиять на отображение каждой полосы. В качестве примера я изменил John на 0 и Susan на 20.

data: [
    ['John', 0],
    ['Mike', 24],
    ['Charles', 10],
    ['Susan', 20],
    ['Rebecca', 56],
],

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

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

В вашей snapshots папке вы должны увидеть __diff_output__ папку с файлом изображения.

Откройте файл, чтобы увидеть результат сравнения изображений.

Левая часть - это базовый снимок. Справа - последний снимок. Среднее изображение - это разница двух снимков, каждое несоответствие выделено красным.

Чтобы по-настоящему оценить возможности визуального тестирования, давайте изменим цвет диаграммы с зеленого на синий. В том же файле src / BarChart.tsx найдите эту строку:

color: 'green',

Измените цвет на ‘blue’.

Повторите тест еще раз, и он все равно не удастся. Давайте посмотрим на сгенерированное изображение сравнения.

Каждая полоса теперь выделена при чтении. Это связано с тем, что при попиксельном сравнении также учитываются значения цвета каждого пикселя.

Заключение

В некоторых проектах вам может потребоваться проверить, как ваш пользовательский интерфейс выглядит для конечного пользователя. Это можно сделать, создав визуальные тесты. Cypress с помощью cypress-image-snapshot plugin позволит вам выполнять визуальные тесты для вашего проекта. Визуальный тест будет выполняться с использованием попиксельного сравнения с базовым изображением, которое было ранее снято. Я надеюсь, что вы узнали что-то ценное и сможете применить это в своих текущих и будущих проектах. Большое спасибо за чтение!