Привет, Хабр!
Несколько дней назад в одной из веток обсуждений в сообществе 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.
Спасибо за внимание и удачного тестирования!