Автоматизация тестов с помощью CodeceptJS и Testomat.io: Первые шаги

Ручное тестирование на лету может оказаться довольно сложным, даже если это «просто счастливый путь».

«Просто (сложный) счастливый путь»

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

Выбор (и смешивание) тестовых фреймворков

В блоге уже достаточно статей о Jest или Cypress, поэтому позвольте мне представить Codecept. Он поставляется в двух вариантах. Есть Codeception для PHP, а есть CodeceptJS для JavaScript, который мы будем использовать здесь.

Testomat.io — это программное обеспечение как услуга для управления автоматизированными тестами для контроля управления качеством.

Импорт практически любого существующего тестового сценария в Testomat.io

Приятно: мы можем импортировать практически любой существующий тест, который у нас уже есть! Jasmine, jest, mocha, cucumber и все остальные классические вещи, или Cypress, Codecept и Codeception из наших последних проектов. (Если у вас нет никаких существующих тестов, перейдите к «продвинутой» части этой статьи, где я покажу вам некоторые способы улучшения моих (не)существующих тестов, это может быть хорошим началом для первого простого сценария).

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

Импорт тестов из исходного кода

TESTOMATIO=__$APIKEY__ npx check-tests@latest CodeceptJS "**/*{.,_}{test,spec}.js"

Выполнив описанные выше действия в командной строке (заменив $APIKEY на наш настоящий, секретный API-ключ, который мы только что получили от Testomat.io), импортер обработает наши данные и выведет сводку:

Обновление тестов из исходного кода

Для обновления запустите тот же скрипт снова.

Настройка отчетности

В настройках мы можем настроить уведомления об отчетах на основе наборов правил, например, какие результаты тестирования (на основе названий тестов или групп) должны сообщаться в каком случае (неудача, успех, всегда) по какому каналу (например, Slack, Jira, Teams или электронная почта).

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

Визуальное тестирование

Использование CodeceptJS для сравнения скриншотов

Codecept сохраняет скриншоты в случае неудачи.

Так что, возможно, мы сможем сделать еще больше со скриншотами, например, записать один в любом случае и сравнить с предыдущей версией. Тогда мы сможем спокойно обновить SASS или PostCSS, не беспокоясь, что какие-то произвольные 5 байт разницы в результирующем 1000-строчном CSS-файле действительно сломают что-то во фронтенде!

Да, мы можем! Документированная как «Визуальное тестирование», функция скриншотов является возможным средством тестирования. Мы можем использовать Resemble.js, который является отличным инструментом для сравнения и анализа изображений, после добавления codeceptjs-resemblehelper в наш проект:

npm install codeceptjs-resemblehelper --save

Этот помощник должен быть добавлен в конфигурационный файл codecept.conf.js для определения папок для хранения файлов изображений скриншотов.

   "helpers": {
      "ResembleHelper" : {
        "require": "codeceptjs-resemblehelper",
        "screenshotFolder" : "./codecept/output/",
        "baseFolder": "./codecept/screenshots/base/",
        "diffFolder": "./codecept/screenshots/diff/"
      }
   }
Вход в полноэкранный режим Выход из полноэкранного режима

Теперь мы можем делать и сравнивать скриншоты в наших тестах!

  I.saveScreenshot('Homepage_Screenshot.png');
  I.seeVisualDiff('Homepage_Screenshot.png', {
    tolerance: 2,
    prepareBaseImage: false
  });
Вход в полноэкранный режим Выйти из полноэкранного режима

Если мы не хотим предоставлять начальное изображение скриншота, мы можем позволить CodeceptJS подготовить начальное «базовое изображение» при первом запуске или после намеренного визуального изменения, временно установив prepareBaseImage: true.

Сгенерированные скриншоты должны быть зафиксированы в нашем git-репозитории.

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

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

I save screenshot "Homepage_Screenshot.png"`
I see visual diff "Homepage_Screenshot.png",`
{"tolerance":2,"prepareBaseImage":false}`
✖ FAILED in 2604ms

-- FAILURES:

1) Homepage
  Test website content and navigation:
    The base image is of 1200 X 1600 and actual image
    is of 900 X 1200. Please use images of same dimensions
    so as to avoid any unexpected results.
Вход в полноэкранный режим Выход из полноэкранного режима

Если это предполагаемое изменение, я могу теперь установить prepareBaseImage: true для воссоздания нового базового изображения при следующем запуске. После этого тесты пройдут и снова покажут зеленый статус, если только не будет обнаружено еще одно новое изменение.

Тестирование скриншотов — это лишь один из аспектов, с которыми раньше было трудно справиться при написании тестов. Поскольку CodeceptJS основан на Playwright, мы можем тестировать iframe, загрузку и скачивание файлов. И (в отличие от Cypress) CodeceptJS имеет режим параллельной работы.

Расширение и улучшение наших локальных тестов

Проверка нашего кода на ложные предположения

Это забавная часть: Я пытался добавить утверждение, что нет ошибки «404 not found», начиная с очень наивного подхода.

I.dontSee('404');
Вход в полноэкранный режим Выход из полноэкранного режима

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

Используйте скриптовые крючки npm до и после тестирования

Если у вас еще нет сервера предварительного просмотра localhost, вы можете добавить его, используя пакет http-server и добавив цель «serve» в package.json (см. пример исходного кода ниже).

Для локального тестирования мы можем объединить процесс линтинга и сборки с автоматизацией тестирования, используя встроенные пре- и постскрипты npm. Разделив наши задачи на pretest, test и posttest, нам не нужно беспокоиться о том, что сервер разработчиков заблокирует терминал, что мы будем вечно ждать тест, который не выполняется, или как заставить Codecept ждать наш сервер, если скрипты выполняются параллельно.

Интеграция линтинга, сборки и тестирования

Прежде чем приступить к сборке и тестированию, давайте убедимся, что наш исходный код проходит статический контроль качества, добавив популярные инструменты линтинга (eslint для JavaScript и stylelint для CSS) в начало нашей цепочки инструментов тестирования:

  1. Линтуйте исходный код с помощью eslint и stylelint.
  2. Соберите исходный код (используя eleventy и postCSS в моем случае, замените на инструменты по вашему выбору).
  3. Запустите сервер разработки на localhost.
  4. Запустите шаги тестирования CodeceptJS (запуск в реальной сессии браузера).
  5. Остановите сервер разработки (используя pkill, как было предложено на StackOverflow).

Локальная установка — краткое описание

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

Скрипты и зависимости в package.json:

  "scripts": {
        "eslint": "eslint src",
        "stylelint": "stylelint src/*.css",
        "build": "npm run eslint && npm run stylelint && ... your own build steps ...",
        "codeceptjs": "codeceptjs run --steps",
        "serve": "npx http-server dist -p 1974 --cors &",
        "pretest": "npm run build && npm run serve",
        "test": "npm run codeceptjs",
        "posttest": "pkill -f http-server"
    },
    "devDependencies": {
        "@codeceptjs/configure": "^0.8.0",
        "codeceptjs": "^3.3.4",
        "eslint": "^8.6.0",
        "http-server": "^14.1.1",
        "playwright": "^1.25.0",
        "puppeteer": "^16.1.0",
        "stylelint": "^14.10.0",
        "stylelint-config-html": "^1.1.0",
        "stylelint-config-standard": "^27.0.0"
    }
}
Вход в полноэкранный режим Выход из полноэкранного режима

Конфигурационный файл Codecept ./codecept.conf.js. Примечание: пожалуйста, обратитесь к последней версии документации по Codecept, чтобы узнать, какой синтаксис следует использовать!

Это простой пример конфигурации, используемый с CodeceptJS 3.3.4, который, вероятно, уже устарел на момент чтения.

const { setHeadlessWhen, setWindowSize } = require('@codeceptjs/configure');

// turn on headless mode when running with HEADLESS=true environment variable
// export HEADLESS=true && npx codeceptjs run
setHeadlessWhen(process.env.HEADLESS);

setWindowSize(1600, 1200);

exports.config = {
  tests: './codecept/*_test.js',
  output: './codecept/output',
  helpers: {
    Puppeteer: {
      url: 'http://localhost:1974',
      show: true,
      windowSize: '1200x900'
    }
  },
  include: {
    I: './codecept/steps_file.js'
  },
  bootstrap: null,
  mocha: {},
  name: 'ingo-steinke.de',
  plugins: {
    pauseOnFail: {},
    retryFailedStep: {
      enabled: true
    },
    tryTo: {
      enabled: true
    },
    screenshotOnFail: {
      enabled: true
    }
  }
}
Войти в полноэкранный режим Выход из полноэкранного режима

Я создал альтернативные конфигурации для использования в различных средах, поэтому я перенес общие параметры конфигурации в ./codecept.common.conf.js, которые я включил в конкретные файлы конфигурации, чтобы избежать избыточного кода проекта.

Здесь я просто предоставляю другой URL для тестирования развернутого сайта на публичном производственном URL:

./codecept.ci.conf.js:

const { setHeadlessWhen, setWindowSize } = require('@codeceptjs/configure');
exports.config = require ('./codecept.common.conf.js');
exports.config.helpers.Puppeteer.url = 'https://www.ingo-steinke.de';

// turn on headless mode when running with HEADLESS=true environment variable
// export HEADLESS=true && npx codeceptjs run
setHeadlessWhen(process.env.HEADLESS);
Вход в полноэкранный режим Выход из полноэкранного режима

Добавление шагов тестов в наш тестовый сценарий

И последнее, но не менее важное: нам нужны определения тестов. Мы можем использовать общий steps_file.js и конкретные тестовые сценарии, такие как этот тестовый сценарий функции «Домашняя страница», определенный в homepage_tests.js.

Здесь мы делаем несколько простых вещей:
Открываем домашнюю страницу («Я нахожусь на странице /») и проверяем, что некоторое ожидаемое содержимое видно. Мы можем указать текст содержимого, конкретные элементы и даже использовать селекторы XPath, если это необходимо.

Хотя мы можем указать размер экрана в нашей конфигурации, нет необходимости в явной прокрутке. Наши утверждения работают со всем документом, как если бы мы использовали «найти на странице» в браузере.

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

Feature('Homepage');

Scenario('Test website content and navigation', ({ I }) => {

  I.amOnPage('/');
  I.see('Ingo Steinke', 'h1');
  I.see('Creative Web Developer');
  I.seeElement('//a[contains(., "privacy")]');

  // find button by caption text, click it ...
  I.click('privacy');
  // ... and verify that this reveals a hidden paragraph.
  I.see('Your legal rights');

  // We can ensure NOT to see something:
  I.dontSeeElement('.error');
  // I.dontSee('404');

  // so the following would fail:
  // I.dontSee('Ingo');
});
Вход в полноэкранный режим Выход из полноэкранного режима

Итак, это простой сценарий тестирования с использованием npm и CodeceptJS. Мы можем расширить все, используя более сложные и менее наивные тестовые сценарии и добавить альтернативные тестовые конфигурации.

Поскольку мы используем Testomat.io для управления автоматизацией тестирования, давайте не забудем обновить наши тестовые определения после того, как мы что-то изменили.

Это запустит наш конвейер lint + build + test, и если он завершится успешно, обновит тестовый набор на сервере Testomat.io. Публикация в git (а точнее, публикация или слияние в моей ветке main) вызовет сборку и развертывание, так что в итоге у нас будет обновленная сборка веб-страницы и обновленные тестовые определения для тестирования этой живой страницы в продакшене.

npm run test && 
TESTOMATIO=__$APIKEY__ npx check-tests@latest CodeceptJS "**/*{.,_}{test,spec}.js && 
git push"
Вход в полноэкранный режим Выход из полноэкранного режима

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