Ручное тестирование на лету может оказаться довольно сложным, даже если это «просто счастливый путь».
- «Просто (сложный) счастливый путь»
- Выбор (и смешивание) тестовых фреймворков
- Импорт практически любого существующего тестового сценария в Testomat.io
- Импорт тестов из исходного кода
- Обновление тестов из исходного кода
- Настройка отчетности
- Визуальное тестирование
- Использование CodeceptJS для сравнения скриншотов
- Расширение и улучшение наших локальных тестов
- Проверка нашего кода на ложные предположения
- Используйте скриптовые крючки npm до и после тестирования
- Интеграция линтинга, сборки и тестирования
- Локальная установка — краткое описание
- Добавление шагов тестов в наш тестовый сценарий
«Просто (сложный) счастливый путь»
Независимо от того, какой из них вы предпочитаете, любой тестовый фреймворк, возможно, лучше, чем не использовать тесты вообще, и есть много популярных вариантов и других менее известных новичков.
Выбор (и смешивание) тестовых фреймворков
В блоге уже достаточно статей о 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) в начало нашей цепочки инструментов тестирования:
- Линтуйте исходный код с помощью eslint и stylelint.
- Соберите исходный код (используя eleventy и postCSS в моем случае, замените на инструменты по вашему выбору).
- Запустите сервер разработки на localhost.
- Запустите шаги тестирования CodeceptJS (запуск в реальной сессии браузера).
- Остановите сервер разработки (используя 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"