TypeScript — все, что нужно для ваших тестов Cypress #frontend@twiliosendgrid
Опубликовано: 2020-11-14Сегодня в Twilio SendGrid мы пишем большинство наших интерфейсных веб-приложений, особенно новые страницы и функции, с помощью TypeScript и React для лучшей проверки типов, удобства сопровождения и документирования нашей кодовой базы. Когда мы впервые начали писать тесты Cypress более двух лет назад, большинство наших объектов страниц, помощников и файлов спецификаций все еще были реализованы на JavaScript, и мы в основном использовали Cypress версии 3.xx. Более поздние тесты уже были написаны на TypeScript, но мы по-прежнему требовалось преобразовать большое количество файлов и перенести их на TypeScript.
Мы хотели воспользоваться преимуществами полной типизации наших компонентов, модульных тестов и тестов Cypress E2E . Что облегчило процесс , так это переход на более новую версию Cypress, чтобы воспользоваться преимуществами встроенной поддержки TypeScript, начиная с Cypress 4.4.0.
Если вы хотите сделать шаг назад и узнать более общие принципы написания E2E-тестов, прочтите этот пост в блоге. Если вы также хотели бы увидеть подробный обзор наиболее распространенных вещей, которые мы использовали или делали раньше при написании тестов Cypress в разных средах, вы можете обратиться к этому сообщению в блоге, прежде чем начать добавлять TypeScript в свои тесты Cypress. В этом сообщении блога предполагается, что вы знакомы с тестами Cypress и уже использовали их API.
Если вы готовы увидеть, как мы печатали, давайте сначала рассмотрим некоторые первоначальные изменения, такие как добавление поддержки TypeScript в Cypress, если вы используете более старую версию.
Миграция с Cypress 3.x на >= 4.4.0
Те, кто уже настроил свою инфраструктуру Cypress для работы с TypeScript в версиях Cypress с 3.xx по 4.4.3, скорее всего, столкнулись с пробами и ошибками при настройке правильной конфигурации препроцессора Webpack в файле plugins/index.js
. Для команды Twilio SendGrid были некоторые ошибки с определенными файлами, которые должны были быть файлами JavaScript в plugins
и папках support
, и возникали трудно отлаживаемые ошибки Cypress. Как только вы получите что-то работающее, это должно выглядеть примерно так.
После обновления с более ранней версии 3.xx мы смогли удалить нашу конфигурацию препроцессора Webpack, заменить наш файл plugins/index.js
файлом index.ts
, немного поработать с tsconfig.json
нашей папки Cypress и, наконец, используя файлы TS в нашей папке Cypress (например, some_page.spec.ts
, index.d.ts
или page_object.ts
) — больше не нужно настраивать препроцессор Webpack, и это просто сработало! Мы были довольны тем, насколько чище и приятнее было не управлять собственной конфигурацией препроцессора Webpack и иметь лучшее покрытие TypeScript для наших файлов, как показано ниже.
Рассмотрев поддержку TypeScript, мы затем рассмотрели пример реального приложения команды Cypress, репозиторий cypress-real-world-app, чтобы узнать больше о том, как лучше печатать. Мы узнали, как вводить cy.task(“pluginName”, { … })
и Cypress.env(“someEnvVar”)
для улучшения цепочки и поддержки типа intellisense при обновлении файлов. Мы также изучили сопроводительную документацию по TypeScript. Это научило нас, как вводить такие вещи, как наша пользовательская команда cy.login()
и как настроить файл конфигурации tsconfig.json
. В примере приложения также есть tsconfig.json
, на который вы можете ссылаться, который может предоставить вам отличную базовую конфигурацию TypeScript, которую вы можете настроить в соответствии со своими предпочтениями. Мы рекомендуем вам быть в курсе последних версий Cypress, погружаться в официальные ресурсы Cypress и экспериментировать с вашими файлами определения типов.
Ввод пользовательских команд
Мы создали несколько глобальных пользовательских команд, таких как cy.login()
, для обработки входа через API, чтобы их можно было повторно использовать во всех наших файлах спецификаций. Вот пример того, как вы можете ввести свою собственную пользовательскую команду входа в систему, используя учетные данные пользователя и возвращая токен аутентификации.
Ввод переменных среды
Для работы с несколькими тестовыми средами, такими как dev и staging, мы воспользовались преимуществами настройки переменных среды, таких как: «testEnv», чтобы указать, в какой среде мы сейчас тестируем, например, staging, «apiHost», чтобы удерживать серверный хост API и другие. переменные. Вы можете напечатать свои Cypress.env()
, чтобы лучше напечатать функции и другие объекты, которые полагаются на использование этих значений переменных среды, подобных этому.
Плагины для набора текста
Мы создали множество подключаемых функций cy.task()
для обработки вызовов API, опроса сервисов и проверки соответствия электронных писем в тестовых почтовых ящиках. Раньше при цепочке вызовов любой из этих функций, например cy.task().then((data) => {})
связанный субъект данных был бы типизирован как any
или unknown
, что не очень хорошо для наших файлов TypeScript. На примерах Cypress мы узнали, как лучше печатать плагины на основе имени плагина и аргументов, передаваемых в вызовах функций. Это позволило нашим файлам TypeScript определить, каким будет связанный тип данных.
Одна тонкая проблема, с которой мы столкнулись, заключалась в том, что имя .then()
и cy.task()
должны точно совпадать с тем, как вы его ввели. проверьте правильность совпадения типов. Иногда, если вы использовали связанную тему из другой функции Cypress, например cy.getCookie(“auth_token”).its(“value”).then((token) => { })
или cy.wrap(data).then((data) => {})
, вам также нужно ввести эти связанные аргументы данных, прежде чем передавать их в качестве аргумента функции cy.task(..., { token, data })
, иначе вы все равно увидите cy.task(...).then((data) => { })
часть данных, типизированная как any
или unknown
. Для вас лучше быть более явным во многих связанных типах функций Cypress, таких как .its(“value”).then((token: string) => {})
или cy.wrap(data).then((data: DataType) => {})
перед передачей их как часть объекта аргументов cy.task()
, чтобы убедиться, что типы снова работают.
Мы создали отдельные файлы Typescript для плагинов, которые будут экспортировать функции для использования в наших plugins/index.ts
. По мере роста количества подключаемых модулей мы рекомендуем вам организовывать реализации функций этих подключаемых модулей по страницам или функциям, чтобы файл plugins/index.ts
небольшим. Вы должны упростить чтение, когда вы определяете все свои cy.task(...)
в вашем файле plugins/index.ts
. Наконец, вы можете ввести эти функции задач в свой index.d.ts
следующим образом:
Собираем все вместе в файл объявления типа
Мы поместили все наши типы для наших пользовательских команд, переменных среды и плагинов в файл index.d.ts
в папке support
. Мы рекомендуем вам поместить все ваши типы Cypress в основной файл определения TypeScript, чтобы все было организовано. Для обхода отсутствующих типов во внешних зависимостях, используемых в вашем тестовом коде Cypress, вы также можете определить файлы модулей, такие как «some-lib.d.ts», которые будут включать в себя декларацию declare module 'some-lib'
, чтобы обойти предупреждения библиотеки TypeScript. Вы даже можете использовать функцию импорта типов TypeScript, чтобы добавить типы/интерфейсы, определенные в других ваших файлах плагинов/утилит, чтобы избежать дублирования определений типов в нескольких файлах. Вы можете добавить эти типы в пространство имен Cypress и организовать их следующим образом:
Ввод объектов тестовых приспособлений, объектов страниц и файлов спецификаций
Когда мы хотим загрузить различных пользователей и метаданные для тестовой среды, мы ранее показали, как мы можем комбинировать переменные среды, такие как «testEnv», со значениями «тестирование» или «постановка», чтобы извлечь «тестирование» или «тестирование». staging» из общего объекта тестовых приспособлений. Вы можете ввести эти объекты среды тестовых приспособлений с универсальными шаблонами для согласованной структуры для всех ваших спецификаций. Для каждой тестовой среды вы можете иметь одни и те же учетные данные пользователя и метаполя, используя универсальный тип для теста, чтобы добавить столько свойств, сколько ему нужно. См. пример ниже.
Ввод объектов страницы и ввод соответствующих спецификационных файлов зависит от используемых вами команд Cypress, плагинов и других утилит. По большей части ввод объектов страницы или спецификационных файлов не требует значительных изменений по сравнению с их аналогами в JavaScript (при условии, что вы уже вводили плагины и вызовы переменных среды). Иногда вспомогательной функции объекта страницы, которую вы определили, может потребоваться ввести некоторые аргументы, или ответ, возвращаемый cy.request()
, может потребоваться ввести с помощью as
например, response.body as SomeType
. В целом, ваш редактор, такой как VSCode, может автоматически определять связанные типы ваших cy.task()
или cy.customCommand()
без необходимости добавлять дополнительные типы в файлы спецификаций, чтобы компенсировать любые предупреждения TypeScript.
Вот пример частей объекта страницы с некоторыми вспомогательными функциями и файлом спецификаций, который использует объект страницы, пользовательскую команду входа в систему и задачи плагина.
Заключение
Добавление TypeScript в наши тесты Cypress помогло нам избежать ошибок и улучшило опыт разработчиков при написании тестов Cypress. При использовании cy.task()
, Cypress.env()
и cy.customCommand()
мы можем улучшить проверку типов аргументов и выходных данных функции, а также воспользоваться преимуществами автозавершения кода в нашей среде IDE, такой как VSCode.
Ключевым моментом является создание вашего собственного файла объявления типа, такого как файл index.d.ts
, в котором вы можете переопределить или расширить интерфейсы «Cypress» и «Chainable» на основе пользовательских команд, переменных среды и функций плагина задач, которые вы используете. с использованием. Затем в файлах объекта страницы и спецификаций TypeScript вы можете использовать эти функции Cypress и наводить указатель мыши или следовать определению ожидаемых типов ввода и вывода.
Кроме того, попробуйте использовать TypeScript с Cypress, так как в более поздних версиях он имеет встроенную поддержку TypeScript. Проверьте, поможет ли это вам более четко документировать функции и избежать неправильного использования API. Ваши тесты TypeScript, скорее всего, по-прежнему будут похожи на ваши тесты JavaScript Cypress, поэтому вы можете постоянно конвертировать некоторые тесты за раз, чтобы сравнивать и сопоставлять подходы.
Если вас интересуют другие сообщения, связанные с тем, что мы узнали из наших тестов Cypress, вот несколько статей, которые вы должны прочитать:
- Что следует учитывать при написании E2E-тестов
- 1000-футовый обзор написания тестов Cypress
- Работа с потоками электронной почты в тестах Cypress
- Идеи по настройке, организации и объединению ваших тестов Cypress
- Интеграция тестов Cypress с Docker, Buildkite и CICD