Все программисты сталкиваются с багами. Если не тестировать код, ошибок в проекте с течением времени становится больше. Поэтому во многих командах есть тестировщик, который ловит баги и сообщает о них команде.
Последние 6 месяцев мы работали над панелью управления электронными ящиками для автоматической доставки посылок. Проект имеет сложную клиент-серверную архитектуру, построенную на фреймворках React и Node.js. В команде на тот момент не было тестировщика, а дополнительно тестировать код своими силами не доходили руки. Отсюда появилось большое количество багов и необходимость тратить время на фиксы и доработки.
Чем Cypress прекрасен для новичков автоматизации?
Уверен, что никакой другой framework для тестирования не имеет такой понятной, объёмной и обширной документации. Она написана на простом английском языке, содержит описание API, тонну полезных гайдов от разработчиков проекта, к примеру — настройка конфигурации.
Cypress для End2end тестирования. Первый взгляд
Каждая страница описывающая дефолтные методы содержит подобную таблицу. В ней находиться описание переменных, аргументов, опшинов и их значения по умолчанию. Также приведены примеры и подсказки, как правильно использовать методы и комбинировать их с другими для достижения результатов. Справа находится меню для быстрой навигации по разделам страницы. Очень удобно в работе, когда что-то забыл, сразу прыгнуть в «Examples» для какой-либо функции.
Документация — огромный плюс Cypress, полагаю, что разработчики потратили на ее создание в разы больше времени, чем на саму разработку. Если выделить пару часиков на чтение, вы спокойно сможете писать тесты на Cypress и настраивать их под свои нужды.
P.S Если с английским совсем не дружите, не беда — у сайта есть русская локализация.
Community
Конечно, оно не на столько велико как у Selenium, но мне всегда удавалось найти решение проблем в «гуглах». Более того, разработчики активно читают github issues и прислушиваются к мнению потребителей. Часто выпускают полезные подкасты и ведут блог .
Простота установки и скорость работы
Установить Cypress невероятно просто!
npm install cypress — все что вам нужно.
Cкорость его работы заслуживает отдельной похвалы. К примеру, мой тест кейс на 100+ шагов пробегает менее, чем за 3 минуты. Все благодаря его архитектуре: Cypress написан на JavaScript, а test runner это и есть браузер. Чем выше скорость интернета, тем быстрее Cypress делает свою работу. Framework автоматически ждет завершения команд, запросов и ассёртов, прежде чем продолжить выполнение.
Поэтому вам не приходится ломать голову с async await!
Что такое Cypress? | Обзор Cypress.
Cypress стимулирует изучать API тестируемого приложения
Рано или поздно вы столкнетесь с тем, что тесты падают из-за фейлов в серверных запросах, и было бы круто их обрабатывать.
В Cypress runner мы можем наблюдать запросы, которые отправляются на сервер.
Так вот, их можно хендлить с помощью cy.route
И в нужный момент проверить ответ сервера:
Таким образом, вы снижаете вероятность фейла, всегда в курсе для чего нужен конкретный endpoint, какие данные принимает и что должен вернуть. Кроме того, определять причину возникновения дефекта в разы проще!
Test runner
Это окно — прекрасный инструмент для debugging процесса, ведь вы в реальном времени видите как выполняется тест. Кроме того, если код изменится, Cypress автоматически перезапустит тест, и вам не нужно делать никаких лишних действий. Даже после выполнения теста вы можете вернуться в любую его часть и посмотреть, что происходило, так как Cypress сохраняет скриншоты и видео.
Отдельного внимание заслуживает помощник для селекторов. Тыкакем на значок «прицела», наводим курсор на нужный элемент и получаем селектор:
Изучение селекторов и assertions
Cypress из-под коробки включает JQuery, Chai и Sinon extensions . Что это дает? Вы получаете мощные инструменты для поиска и проверки DOM элементов, которые давно себя зарекомендовали. Гугл изобилует информацией про каждый из них. Пример моих помощников: Xpath helpers, JQueary cheat sheet, CSS selectors
Итоги
Если вы только пробуете себя в автоматизации, я рекомендую учиться работая в Cypress. Конечно он не идеален, к примеру мне в работе попались: проблема с отправкой form-data и cross origin error. Так же Cypress не позволяет запускать тесты в нескольких табах одновременно и переходить на другие ресурсы.
Но я хотел сделать упор на достоинствах этого инструмента для легкого старта в автоматизированном тестировании! Ведь научится писать тесты с помощью этого framework`а не трудно благодаря шикарной документации и интуитивно понятном синтаксисе. Согласитесь, свичнуться на что-то другое не станет проблемой, если вы получили хорошую базу.
- автоматизация тестирования
- qa automation
- qa
- cypress
- тестирование
- testing framework
- Тестирование IT-систем
- Тестирование веб-сервисов
Источник: habr.com
Шаги
Тебе нужно разместить тестовое веб-приложение на локальном веб-сервере.
- Установи через терминал пакет npm i tiny-server —save-dev
- В package.json добавь команду start в раздел scripts для запуска сервера:
«scripts»:
- Запусти в терминале npm start
- Открой в Chromehttp://localhost:3000
+2. Загрузка тестового приложения
Веб-сервер готов, нужно скачать тестовое приложение с GitHub.
- Установи Wget npm i node-wget —save-dev
- Создай папку apps в корне проекта.
- Выполни команду:
npx wget -d apps/ https://open-tutorials.github.io/cypress/apps/deep-cypress.html
- Проверь, что появился файл ~/apps/deep-cypress.html
- Обнови страницу в Chrome.
- В списке файлов выбери apps/deep-cypress.html
+3. Поиск элементов в DOM
- Создай файл теста deep-cypress.spec.js с содержимым:
- Проверь, что тест проходит.
- Измени код:
- Проверь, что тест провален.
- ❓ Что такое timeout ?
- ❓ Почему при значении 5000 тест проходит, а при 3000 нет?
- ❓ Какой timeout в Cypress по умолчанию?
Кстати, в Selenium ты бы написал:
const locator = By.css(‘section[data-cy=long-like] [data-cy=success]’); driver.wait(until.elementLocated(locator), 3000);
- Добавь в файл cypress.json :
+ «defaultCommandTimeout»: 10000
- Не забудь отформатировать JSON.
- Перезапусти Cypress.
- Убери timeout в коде для команды:
- Проверь, что тест снова выполняется успешно.
- ❓ Что делает параметр defaultCommandTimeout ?
+4. Цепочки команд
- Добавь новый тест:
- Не забудь удалить у предыдущего теста .only
- Проверь, что тест проходит.
- Измени код:
- Проверь, что тест провален.
- ❓ Почему тест перестал проходить?
If the assertion that follows the cy.get() command passes, then the command finishes successfully.
- Найди этот комментарий на cypress.io
- Измени код:
- Проверь, что тест снова выполняется успешно.
- ❓ Почему тест снова проходит?
+5. Работа с несколькими вкладками
По умолчанию, браузер запрещает взаимодействие между HTML документами загруженными из различных источников (доменов).
Если нам потребуется в Cypress переходить между различными сайтами, нам нужно отключить данную политику безопасности.
- Добавь в файл cypress.json :
+ «chromeWebSecurity»: false
- Перезапусти Cypress.
- Добавь новый тест:
- Проверь, что тест проходит.
- ❓ Что делает cy.title() ?
- Измени код:
- Проверь, что тест провален.
- ❓ Что не может сделать Cypress?
- ❓ За что отвечает аттрибут target в ссылках?
- ❓ Что делает команда invoke(‘removeAttr’, ‘target’) ?
Понять и простить — Cypress не поддерживает управление несколькими вкладками
- Верни код обратно.
+6. Заглушка функций
6.1. Переписываем window.open
- Добавь новый тест:
- Проверь, что тест провален.
- Проинспектируй HTML код кнопки.
- ❓ Что не может сделать Cypress?
- ❓ Что делает кнопка на onclick ?
- ❓ Что такое window.open?
- Добавь код перед нажатием на кнопку:
+ cy.window().then((window) => < + cy.stub(window, ‘open’).callsFake((url) =>< + console.log(‘we have implemented own window.open function’); + window.location = url; + >); + >);
- Проверь, что тест проходит.
- ❓ Что ты сделал с помощью команды stub ?
- ❓ Что делает window.location = url ?
6.2. Переписываем window.prompt
- Добавь новый тест:
- Проверь, что тест проходит.
- Проинспектируй HTML код кнопки.
- ❓ Что такое window.prompt?
- ❓ Что делает функция showPrompt внутри приложения?
- ❓ Зачем мы возвращаем XYZ ?
6.3. Переписываем клик по кнопке
- Добавь новый тест:
- Проверь, что тест проходит.
- Проинспектируй HTML код секции.
- Закомментируй invoke(‘on’, . )
- Проверь, что тест провален.
- ❓ Что мы поместили в алиас fakeClick ?
- ❓ Что делает invoke(‘off’, ‘click’) ?
- ❓ Что мы сделали с помощью invoke(‘on’, ‘click’, fake) ?
+7. Работа с iframe
- Добавь новый тест:
— .should(‘not.be.empty’)
- Проверь, что тест провален.
- ❓ Что не может сделать Cypress?
- Верни код обратно.
+8. Теневой DOM
- Добавь новый тест:
- Проверь, что тест провален.
- Проинспектируй HTML код секции.
User should say hello.
#shadow-root ↓ p
- Измени код:
- Проверь, что тест проходит.
- ❓ Что делает shadow() ?
+9. Инвоук
9.1. Манипуляции DOM
Cypress может взаимодействовать с DOM: вызывать функции, читать и устанавливать аттрибуты элементов и т.д.
- Добавь новый тест:
- Проверь, что тест проходит.
- Проинспектируй HTML секции.
- ❓ Что делает invoke(‘css’, . ) ?
- ❓ Что делает cy.window().invoke() ?
- ❓ Что делает invoke(‘html’) ?
9.2. jQuery
Cypress очень любит jQuery — в свое время популярную библиотеку на Java Script.
- Зайди на google.com
- Открой инструменты разработчика и выполни скрипт:
document.querySelector(‘body’).style.backgroundColor = ‘red’;
- ❓ Залил гугл красным?
На jQuery ты бы написал:
$(‘body’).css(‘background-color’, ‘red’);
$ — супер функция предоставляющая доступ к возможностям API библиотеки.
Лозунг jQuery — пиши меньше, делай больше!
9.3. Рецепты
Для целей тестирования тебе могут быть полезны ряд рецептов для работы с DOM.
- Взять текст внутри элемента и очистить его от пробелов и переносов строк:
cy.get(‘selector’) .invoke(‘text’) .invoke(‘trim’) .should(‘eq’, ‘?’);
- Установить/взять внутренний HTML внутри элемента:
cy.get(‘selector’) .invoke(‘html’, ‘Bold’); cy.get(‘selector’) .invoke(‘html’) .should(‘contains’, ‘Bold’);
- Установить/взять CSS свойство элемента:
cy.get(‘selector’).invoke(‘css’, ‘background-color’, ‘red’); cy.get(‘selector’).invoke(‘css’, ‘background-color’).should(‘eq’, ‘red’);
- Взять/установить ширину и высоту элемента:
cy.get(‘selector’).invoke(‘width’, ‘200px’); cy.get(‘selector’).invoke(‘width’).should(‘greaterThan’, 200); cy.get(‘selector’).invoke(‘height’, ‘100px’); cy.get(‘selector’).invoke(‘height’).should(‘greaterThan’, 100);
- Взять абсолютную позицию элемента на странице:
cy.get(‘selector’).invoke(‘position’).then(() => < cy.log(left, top); >);
- Добавить/удалить CSS класс active у элемента:
cy.get(‘selector’) .invoke(‘addClass’, ‘active’) .should(‘have.class’, ‘active’); cy.get(‘selector’) .invoke(‘removeClass’, ‘active’) .should(‘not.have.class’, ‘active’);
- Узнать наличие CSS класса active у элемента:
cy.get(‘selector’) .invoke(‘hasClass’, ‘active’) .then(active => < if (active) < cy.log(‘has active class’); >else < cy.log(‘has not active class’); >>);
- Взять/установить аттрибут элемента:
cy.get(‘selector’).invoke(‘attr’, ‘src’, ‘?’); cy.get(‘selector’).invoke(‘attr’).should(‘eq’, ‘?’);
+10. Триггеры
10.1. Нажатие мышкой
- Добавь новый тест:
- Проверь, что тест проходит.
- Прочитай спецификацию на команду trigger
- ❓ Что делает trigger(‘mousedown’) ?
- ❓ Что делает cy.wait(3000) ?
- ❓ Что делает trigger(‘mouseup’) ?
10.2. Движение мышкой
- Проверь, что тест проходит.
- Прочитай спецификацию на mousemove
- ❓ Что делает position() ?
- ❓ Что делает its(‘top’) ?
- ❓ Что делает trigger(‘mousemove’, ?
- ❓ Что будет если установить cy.wait(50) ?
+11. Вьюпорт
- Добавь новый тест:
- Проверь, что тест проходит.
- Прочитай спецификацию на команду viewport
- ❓ Что делает scrollIntoView() ?
- ❓ Что делает viewport(‘iphone-4’) ?
- ❓ Что делает should(‘have.css’, . ) ?
- ❓ Как сделать этот тест для iPhone14?
+12. Скриншоты
- Проверь, что тест проходит.
- Найди файлы скриншотов ~/cypress/screenshots
- Что делает invoke(‘css’, ‘background’, ‘green’) ?
- Что значит before и after ?
+13. Перехват сетевых запросов
- Добавь новый тест:
Кстати, так можно перехватить не только XHR запросы, но и картинки, стили даже iframe и т.д.
+14. Локейшен
Переходя по ссылкам мы проверяем, что URL приложения меняется.
cy.url() — возвращает базовый URL + текущий путь страницы внутри приложения.
cy.url().should(‘include’, ‘/’);
Код выше будет работать для всех страниц приложения т.к. они все начинаются с /
❓ Как тогда проверить, что мы перешли именно на главную страницу / ?
- Добавь новые тесты:
- ❓ Что делает cy.location(‘pathname’) ?
- ❓ Что делает cy.location(‘search’) ?
- ❓ Что делает cy.location(‘hash’) ?
+15. Грабим сайты
Ничего криминального grab — это захватывать.
- Добавь новый тест:
- Проверь, что тест проходит.
- Проверь содержимое файла ~/tmp/users.json
- Проинспектируй HTML секции и сравни с JSON в файле.
- ❓ Что содержит массив row.children ?
- ❓ Зачем нужен return users ?
Очень интересно, но ничего не понятно?
- Создай файл ~/js_examples/read_html_table.js с содержимым:
- Запусти файл.
- Добавь себя в таблицу.
- ❓ Что возвращает функция получитьПользователей() ?
+16. Промисы для искушенных
- Добавь новый тест:
- Проверь, что тест проходит.
- Открой консоль в Chrome под Cypress.
- Повтори тест несколько раз.
- Сверь журнал вывода Cypress и консоль в Chrome.
- ❓ Что такое Cypress.Promise ?
- ❓ Что такое setTimeout ?
- ❓ Почему в консоли Chrome порядок не правильный — acb ?
+17. Еще полезные рецепты
17.1. Установка скоупа
По умолчанию, cy.get ищет элементы внутри всего документа.
Register
cy.get(‘form[name=signup] input[name=email]’).type(‘?’); cy.get(‘form[name=signup] input[name=password]’).type(‘?’); cy.get(‘form[name=signup] button[type=submit]’).click();
Ты уже знаешь, как сократить код через алисы:
Можно сделать еще короче через установку скоупа:
// scope документа cy.get(‘form[name=signup]’).within(() => < // scope формы cy.get(‘input[name=email]’).type(‘?’); cy.get(‘input[name=password]’).type(‘?’); cy.get(‘button[type=submit]’).click(); >); // снова scope документа
Скоуп / scope — позволяет определить область / рамки / границы действия команд. ~»В конспект»
17.2. Луп / loop по элементам
~»Кейс:» проверить корректность ссылок в верхнем меню.