Привет, Хабр!

Несколько дней назад в одной из веток обсуждений в сообществе Cypress на Discord мельком был затронут вопрос о том, как проверить данные из файла Excel с помощью Cypress. Это подтолкнуло меня сделать несколько полезных заметок, ставших основой для данной статьи.

Забегая вперед лишь отмечу, что дело это довольно нехитрое, и в основном сводится к настройке соответствующего node события внутри файла конфигурации Cypress для преобразования исходного Excel файла к формату JSON и дальнейшей работе с полученным файлом. Но обо всем по порядку.

Если вы еще не знакомы с Cypress, то кратко данный инструмент можно охарактеризовать следующим образом:

Cypress — это инструмент сквозного тестирования на основе JavaScript, разработанный для современной автоматизации веб-тестирования. Cypress стал популярным инструментом сквозного тестирования веб-приложений благодаря своим сравнительно мощным функциям, удобному интерфейсу и быстроте выполнения тестов.

Вместе с тем очевидно, что Cypress не предназначен для тестирования данных Excel, что в некоторых тестовых сценариях может создать некоторые неудобства в случае необходимости проверки данных в файлах Excel. Несмотря на это, Cypress предоставляет способ сделать это, как я уже отмечал ранее, путем преобразования Excel файла в формат JSON, совместимый с Cypress. Это позволяет тестировать исходные данные с использованием того же набора тестов, которые используются для тестирования веб-приложений.

Что ж, давайте представим, что в ходе выполнения некоторого тестового сценария мы получаем некий companies.xlsx файл в директории cypress/downloads нашего проекта. В сущности сценарий может быть любым, как и начальное расположение исходного файла.

Предположим также, что перед нами стоит задача протестировать данные в этом файле, которые содержат информацию о следующих десяти компаниях:

Для начала преобразуем исходный companies.xlsx файл в формат JSON. Собственно, для этого есть несколько подходящих npm пакетов, самый популярный из которых на сегодняшний день (судя по количеству еженедельных скачиваний) - SheetJS. Давайте установим его в проект, введя в терминале следующую команду:

> npm i xlsx

Далее, учитывая синтаксис данного пакета, добавим task событие в блок setupNodeEvents в cypress.config.ts файле. Это обеспечит нам возможность перехода из среды браузера в среду Node и выполнения в данной среде некоторой заданной JavaScript функции. Например, назовем нашу функцию convertXlsxToJson, с ее помощью мы преобразуем исходный Excel файла в JSON формат:

Так, наша функция convertXlsxToJson принимает в качестве аргумента путь к исходному Excel файлу - filePath и использует метод XLSX.readFile() для чтения файла, в результате чего мы получаем некий объект workbook с довольной сложной структурой, содержащий данные исходной рабочей книги Excel. Давайте разберем его подробней.

Ключевым элементом объекта workbook является объект Sheets, свойства которого также представляют собой объекты, содержащие отдельные рабочие листы в исходной рабочей книге Excel, при этом ключи - это имена рабочих листов, а значения - объекты, представляющие каждый рабочий лист. В свою очередь, каждый объект рабочего листа имеет собственный набор свойств, у которых ключами являются ссылки на ячейки в рабочем листе (например A1, B2 и т. д.), а значениями выступают объекты, содержащие информацию о типе данных в конкретной ячейке, а также непосредственно само значение ячейки. Также объект workbook содержит в себе массив SheetNames с именами рабочих листов книги, при этом порядок имен в массиве соответствует порядку рабочих листов в книге. Кроме того, объект workbook включает ряд иных свойств, содержащих данные об исходной книге Excel.

Для извлечения имени первого рабочего листа, включающего таблицу с данными о компаниях (очевидно, что это мог быть любой другой лист), мы обращаемся к значению нулевого элемента массива SheetNames. Далее используя полученное имя листа как ключ соответствующего свойства у объекта Sheets, мы получаем объект рабочего листа как значение этого свойства и помещаем его в переменную worksheet.

К указанной переменной мы применяем метод XLSX.utils.sheet_to_json() для преобразования данных рабочего листа в формат JSON. В результате мы имеем массив объектов jsonData, в котором каждый объект соответствует определенной строке исходной таблицы. Свойства в каждом объекте включают заголовки столбцов (ключи) и соответствующие данные в ячейках (значения). В конечном итоге, наша функция convertXlsxToJson возвращает массив jsonData в качестве результата выполнения task события.

В целом на этом этапе задача может считаться выполненной, поскольку переменная jsonData содержит данные в формате JSON, пригодном для использования в тестах. Однако давайте представим, что мы хотим записать полученные данные в виде companies.json файла и поместить его, например, в директорию cypress/fixtures (очевидно, мы можем выбрать любое другое расположение файла)Для этого дополним нашу функцию convertXlsxToJson следующими строками кода:

Так, вначале мы определяем переменную fileName, в которую помещаем имя исходного Excel файла (без расширения), полученное на основе значения переменной filePath с помощью метода path.basename(). Используя указанное имя файла, задаем в переменной jsonFilePath путь до результирующего JSON файла в директории fixtures. И в завершение мы используем метод writeFileSync() из встроенного fs модуля Node.js, который синхронно записывает данные в результирующий файл в виде отформатированной JSON строки с двумя пробелами для каждого уровня отступа с помощью метода JSON.stringify().

Таким образом, мы настроили наше task событие convertXlsxToJson таким образом, что оно принимает любой Excel файл, расположенный по указанному пути, считывает его и преобразует в JSON формат, а также записывает результирующий JSON файл в директорию fixtures.

Теперь чтобы протестировать исходные данные десяти компаний, создадим spec-файл testExcel.cy.ts в e2e директории. Во-первых, добавим в блок describe хук before, в котором мы будем вызывать наше task событие, передавая ему в качестве аргумента путь к исходному Excel файлу:

После вызова taskсобытия в директорию fixtures будет записан результирующий файл companies.json:

имеющий следующую структуру:

После добавления тестов наш spec-файл, наконец, будет выглядеть следующим образом:

Так, вначале мы определяем две переменные: xlsxPath - путь к исходному Excel файлу и jsonName - имя итогового JSON файла, получаемое на основе значения переменной xlsxPath с помощью методов path.basename() и replace(). Далее внутри beforeEach хука мы используем команду cy.fixture() для загрузки содержимого итогового JSON файла в виде фикстуры, которому присваиваем псевдоним companiesData для доступа к указанному содержимому в каждом тесте.

В качестве возможных примеров тестов я привел три довольно примитивных демонстрационных теста. Так, первый тест проверяет, содержит ли наш тестируемый файл данные 10 компаний. Второй позволяет убедиться в наличии в данных каждой компании непустых значений для четырех ключей — «Название компании», «Продукт», «Город» и «Электронная почта». И последний тест проверяет, содержат ли данные каждой компании уникальный адрес электронной почты. 

Давайте запустим наши тесты в тест-раннере Cypress с помощью стандартной команды:

> npx cypress open

Кликаем по имени spec-файла в окне тест-раннера и вуаля - наши тесты успешно завершились менее чем, за 0,1 секунды:

Вместо заключения

Хотя Cypress можно использовать для проверки данных Excel, очевидно, это не относится к его основной функциональности. Cypress не тестирует Excel файлы что называется "из под капота". Поэтому следует помнить о возможных ошибках, которые могут возникнуть на этапе преобразования Excel файла в JSON формат, таких как ошибки форматирования, потери данных и пр., которые впоследствии могут привести к нежелательным результатам. Несмотря на относительную редкость описанного кейса и сравнительную незамысловатость подхода к его решению, я очень надеюсь, что данная статья будет полезна для совершенствования ваших навыков тестирования с помощью Cypress.

Чтобы получить больше информации о тестировании с помощью Cypress, вы можете подписаться на мой блог «Тестирование с помощью Cypress» (на английском языке) на Medium.com, чтобы получать уведомления о выходе новых статей.

Исходный код, а также файлы, представленные в данной статье, вы можете найти в соответствующем репозитории моего блога на GitHub.

Спасибо за внимание и удачного тестирования!

Комментарии (8)