Добавление тестов Cypress в проект TypeScript и развертывание в Netlify

Конечное тестирование дает нам много преимуществ, когда речь идет о тестировании программного обеспечения. Добавив даже один тест, мы можем охватить достаточно большую территорию с точки зрения проверки функциональности приложения с точки зрения конечного пользователя. Вот как я настроил Cypress в проекте TypeScript и развернул его в Netlify, воспользовавшись преимуществами CI.

Начало работы

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

Добавление зависимостей

Начнем с добавления Cypress и Cypress Testing Library в список зависимостей.

yarn add -D cypress @testing-library/cypress
Войдите в полноэкранный режим Выход из полноэкранного режима

Библиотека тестирования Cypress дает нам дополнительные команды, findBy, findAllBy, queryBy и queryAllBy, с которыми работать еще приятнее. Это необязательно, но рекомендуется. Подробности смотрите в документации.

Настройка Cypress

Чтобы настроить Cypress так, чтобы мы могли писать тесты на TypeScript, нам понадобятся следующие файлы: cypress.config.ts, cypress/support/e2e.ts, cypress/support/commands.ts, и cypress/tsconfig.json.

Давайте рассмотрим каждый из них.

// cypress.config.ts
import { defineConfig } from "cypress"

export default defineConfig({
  e2e: {
    baseUrl: "http://localhost:8000",
  },
})
Войти в полноэкранный режим Выход из полноэкранного режима

Обратите внимание, что baseUrl будет тем, который вы используете для вашего сервера разработки. Это может быть http://localhost:3000 или http://localhost:8080 или что-то подобное.

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

// cypress/support/e2e.ts
import "./commands"
import "cypress-axe"
import "@testing-library/cypress/add-commands"
Вход в полноэкранный режим Выход из полноэкранного режима
// cypress/support/commands.ts
/// <reference types="cypress" />
/// <reference types="@testing-library/cypress" />
Войти в полноэкранный режим Выход из полноэкранного режима

👌 Все дело в завершении кода!

И, наконец, рекомендуемый tsconfig.json выглядит следующим образом:

// cypress/tsconfig.json
{
  "extends": "../tsconfig.json",
  "compilerOptions": {
    "target": "es5",
    "lib": ["es5", "dom"],
    "types": ["cypress", "@testing-library/cypress"],
    "noEmit": true
  },
  "include": ["./**/*.ts"]
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Настроить ESLint

Если мы не настроим ESLint, то получим кучу красных загогулин, так что давайте сделаем наш линтер счастливым, а нашу жизнь проще.

yarn add -D eslint-plugin-cypress
Войти в полноэкранный режим Выйдите из полноэкранного режима

И добавьте следующий файл в каталог cypress:

// cypress/.eslintrc.json
{
  "plugins": ["cypress"]
}
Enter fullscreen mode Выйти из полноэкранного режима

Вот и все!

Пишем тесты

Теперь начинается настоящее веселье! Давайте напишем наш первый тест для проверки доступности наших страниц. Для этого нам нужно добавить зависимость для использования API веб-тестирования axe-core.

yarn add -D cypress-axe axe-core
Вход в полноэкранный режим Выход из полноэкранного режима

Утверждается, что с помощью этой библиотеки мы можем автоматически найти в среднем 57% проблем WCAG. Кроме того, этот инструмент направит наше внимание на ряд ручных проверок, на которые нам следует обратить более пристальное внимание.

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

И не забудьте также обновить конфигурацию TypeScript:

// cypress/tsconfig.json
{
  "extends": "../tsconfig.json",
  "compilerOptions": {
    "target": "es5",
    "lib": ["es5", "dom"],
    "types": ["cypress", "@testing-library/cypress", "cypress-axe"], // highlight-line
    "noEmit": true
  },
  "include": ["./**/*.ts"]
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Теперь давайте напишем первый тест!

// cypress/e2e/accessibility.cy.ts
describe("Accessibility tests", () => {
  it("Has no detectable accessibility violations on load", () => {
    cy.visit("/").get("main").injectAxe()
    cy.checkA11y(null, {
      includedImpacts: ["critical", "serious", "moderate"],
    })
  })
})
Войти в полноэкранный режим Выход из полноэкранного режима

Итак, что же здесь происходит? Ну, у нас есть один тест, загружающий главную страницу, просматривающий main и выполняющий наши тесты доступности. Мы рассматриваем «критические», «серьезные» и «умеренные» нарушения, которые вы можете изменить в соответствии со своими потребностями.

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

// cypress/e2e/accessibility.cy.ts
const axeRunContext = {
  exclude: [[".prism-code"]],
}

const axeRunOptions = {
  includedImpacts: ["critical", "serious", "moderate"],
}

describe("Accessibility tests", () => {
  beforeEach(() => {
    cy.visit("/").get("main").injectAxe()
  })
  it("Has no detectable accessibility violations on load", () => {
    cy.checkA11y(null, axeRunOptions)
  })
  it("Navigates to blog post and checks for accessibility violations", () => {
    cy.findByText(/making a create react app template/i)
      .click()
      .checkA11y(axeRunContext, axeRunOptions)
  })
})
Вход в полноэкранный режим Выход из полноэкранного режима

Мы можем исключить определенные селекторы CSS, и в данном случае мы исключаем .prism-code. Многократная проверка блоков кода может быть дорогостоящей. В идеале мы можем один раз проверить их в отдельных тестах и пропустить во всех остальных. Это удобный способ сделать это.

Запуск тестов локально

Когда Cypress установлен, настроен и написан наш первый тест, мы готовы начать вечеринку.

Вы можете запустить тесты следующим образом:

yarn run cypress open
Войти в полноэкранный режим Выйти из полноэкранного режима

🥳 Ура! Мы проводим сквозное тестирование всех вещей!

Если вы впервые используете Cypress, вы можете влюбиться в него, как и я. Он делает тестирование намного проще и с ним приятно работать по сравнению с альтернативами, которые я рассматривал.

Давайте рассмотрим некоторые способы улучшения работы.

Добавьте скрипты npm

Теперь добавим несколько скриптов в package.json, чтобы облегчить нашу жизнь:

"scripts": {
  "cy:open": "cypress open",
  "cy:run": "cypress run",
  "test:e2e": "start-server-and-test develop http://localhost:8000 cy:open",
  "test:e2e:ci": "start-server-and-test develop http://localhost:8000 cy:run",
}
Вход в полноэкранный режим Выход из полноэкранного режима

Нам также нужно добавить start-server-and-test, чтобы мы могли запускать наши тесты, не беспокоясь о том, запущен ли сервер разработки в другом терминале.

yarn add -D start-server-and-test
Вход в полноэкранный режим Выход из полноэкранного режима

И еще одна деталь, не забудьте добавить cypress/videos и cypress/screenshots в ваш .gitignore, поскольку нам не нужно будет отслеживать их в системе контроля версий.

Для локального запуска наших тестов мы будем использовать:

yarn test:e2e
Войти в полноэкранный режим Выйти из полноэкранного режима

И вы заметите, что мы также можем запустить Cypress без головы, что полезно при запуске из командной строки и использовании с Continuous Integration (CI):

yarn test:e2e:ci
Войти в полноэкранный режим Выход из полноэкранного режима

Непрерывная интеграция

Этот последний шаг будет выглядеть по-разному в зависимости от того, какой CI вы используете и как он у вас настроен.

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

В идеале, это будет сопровождаться как минимум двумя мерами предосторожности: тестированием перед развертыванием в CI и тестированием на GitHub перед разрешением слияния.

В этом примере я покажу вам, как это сделать с помощью Netlify, которая имеет хорошо продуманную и удобную для разработчиков платформу CI.

Настройка Netlify

Во-первых, нам понадобится netlify-plugin-cypress.

yarn add -D netlify-plugin-cypress
Войдите в полноэкранный режим Выйти из полноэкранного режима

Самая базовая рекомендуемая настройка выглядит следующим образом:

# explicit commands for building the site
# and the folder to publish
[build]
command = "yarn build"
publish = "public"

[build.environment]
# cache Cypress binary in local "node_modules" folder
# so Netlify caches it
CYPRESS_CACHE_FOLDER = "./node_modules/CypressBinary"
# set TERM variable for terminal output
TERM = "xterm"

[[plugins]]
# runs Cypress tests against the deployed URL
package = "netlify-plugin-cypress"
Войти в полноэкранный режим Выйти из полноэкранного режима

Однако это приводит к определенной проблеме: по умолчанию Netlify запускает тесты Cypress после успешной сборки и развертывания. У нас может быть вполне работоспособная сборка с технической точки зрения, но с потенциально неудачными тестами, и мы не хотим, чтобы это попало в производство.

С помощью нескольких дополнительных строк мы можем потребовать тесты в два других момента: (1) до сборки (preBuild) и (2) после сборки (postBuild), но до развертывания (onSuccess).

Я рекомендую вам выбрать один из первых двух вариантов или оба, чтобы запустить все ваши тесты, а затем выполнить быструю проверку на вменяемость после развертывания. Такой вид тестирования часто называют дымовым.

Я выбрал запуск тестов перед сборкой следующим образом:

# netlify.toml
[build]
  command = "yarn build"
  publish = "public"
[build.environment]
  CYPRESS_CACHE_FOLDER = "./node_modules/CypressBinary"
  TERM = "xterm"
[[plugins]]
  package = "netlify-plugin-cypress"
  [plugins.inputs.preBuild]
    enable = true
    start = 'yarn start'
    wait-on = 'http://localhost:8000'
    wait-on-timeout = '30'
Войти в полноэкранный режим Выйти из полноэкранного режима

Хорошо, отлично, теперь, если код каким-то образом будет отправлен на развертывание, а тесты не пройдут, развертывание будет остановлено. Это то, чего мы хотим.

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

Добавим дымовой тест

Давайте добавим еще один тест:

// cypress/e2e/smoke.cy.ts
describe("Smoke test", () => {
  it("should visit the index page and particular blog post", () => {
    cy.visit("/")
      .get("main")
      .should("exist")
      .findByText(/making a create react app template/i)
      .click()
      .get("main")
      .should("exist")
  })
})
Вход в полноэкранный режим Выход из полноэкранного режима

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

Давайте снова настроим netlify.toml:

# netlify.toml
[build]
  command = "yarn build"
  publish = "public"
[build.environment]
    CYPRESS_CACHE_FOLDER = "./node_modules/CypressBinary"
    TERM = "xterm"
[[plugins]]
  package = "netlify-plugin-cypress"
  [plugins.inputs] // highlight-line
    spec = "cypress/e2e/smoke.cy.ts" // highlight-line
  [plugins.inputs.preBuild]
    enable = true
    start = 'yarn start'
    wait-on = 'http://localhost:8000'
    wait-on-timeout = '30'
Войти в полноэкранный режим Выйти из полноэкранного режима

Теперь тесты будут запускаться до сборки (preBuild), и только дымовой тест будет запущен после развертывания (onSuccess).

Но подождите, есть еще кое-что.

Пока все хорошо, но дальше будет только лучше.

🍰 Как насчет того, чтобы добавить немного глазури на этот торт?

Вы знаете, что при локальной разработке вы получаете скриншоты и видео с тестами? Насколько я знаю, в Netlify CI нет возможности получить эти материалы без дополнительных усилий.

Если вы еще не сделали этого, перейдите на cypress.io и создайте учетную запись. Если вы хотите остаться на бесплатном уровне, вам придется сделать все публичным, что меня вполне устраивает.

Теперь вы можете наблюдать за своими неудачами на публике 😂. Это закаляет характер.

Но на самом деле, у меня было несколько крайних случаев, когда локально все проходило, а в CI все проваливалось, что, скорее всего, давало повод еще раз взглянуть на ситуацию. Итак, нам действительно нужно время от времени смотреть на эти активы, и Cypress Dashboard — это решение!

Для этого нам нужно сделать еще пару вещей.

Во-первых, давайте еще раз настроим netlify.toml:

# netlify.toml
[build]
  command = "yarn build"
  publish = "public"
[build.environment]
    CYPRESS_CACHE_FOLDER = "./node_modules/CypressBinary"
    TERM = "xterm"
[[plugins]]
  package = "netlify-plugin-cypress"
  [plugins.inputs]
    record = true // highlight-line
    spec = "cypress/e2e/smoke.cy.ts"
  [plugins.inputs.preBuild]
    enable = true
    start = 'yarn start'
    wait-on = 'http://localhost:8000'
    wait-on-timeout = '30'
    record = true // highlight-line
Войти в полноэкранный режим Выйти из полноэкранного режима

После этого возьмите две вещи из вашей учетной записи Cypress: ID проекта и ключ записи, оба в разделе Настройки проекта.

Теперь обновите cypress.config.ts:

import { defineConfig } from "cypress"

export default defineConfig({
  projectId: "a7bq2k",
  e2e: {
    baseUrl: "http://localhost:8000",
  },
})
Войти в полноэкранный режим Выход из полноэкранного режима

И объявите переменную окружения сборки CYPRESS_RECORD_KEY в Netlify. Если вы не знаете, как это сделать, прочитайте о том, как это сделать здесь. Установите CYPRESS_RECORD_KEY на ключ записи, который вы получили из учетной записи Cypress.

🔌 Мы подключены! Теперь мы записываем наши тесты из процесса сборки Netlify и можем просматривать эти видео и скриншоты, когда нам это необходимо.

Интеграция с GitHub

🍒 И в качестве вишенки на вершине мы можем интегрироваться с GitHub. Посмотрите на приложение Cypress GitHub App.

Я рекомендую вам сделать это и настроить ваш репозиторий таким образом, чтобы процесс Netlify стал зеленым, прежде чем вы сможете объединиться. Это обеспечит еще один уровень защиты.

Подведение итогов

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

Я надеюсь, что это может помочь некоторым людям. Если есть вопросы, дайте мне знать, и я постараюсь ответить.

Комментируйте ниже или пишите мне в Твиттере.

Оцените статью
devanswers.ru
Добавить комментарий