Подойдет тем, кто хочет писать устойчивые, понятные и короткие селекторы в авто-тестах.
Задача End-To-End тестов — заставить компьютер нажимать на кнопки, вводить данные в поля формы, двигать мышкой — как это делал бы человек.
Селекторы / локаторы — позволяют находить элементы UI с которыми ты будешь заставлять машину взаимодействовать.
Селекторы — основная часть будущего исходного кода твоих тестов.
От того, насколько хорошо ты будешь находить селекторы элементов, твой код будет:
🤮 Твой код до:
cy.get('body main div[class="panel"] form .input-primary').type('?');
cy.get('body .form #xxyyzz').type('?');
cy.get('[class="btn btn-primary"]').click();
🤩 Твой код после:
cy.get('form.login input[name=email]').type('?');
cy.get('form.login input[name=password]').type('?');
cy.get('form.login button[type=submit]').click();
%/projects/cypress/best_selectors
npm i cypress@9 --save-dev
Если забыл, глянь в наш первый туториал
Помни: никто тебя ничему не научит, если ты сам этого не захочешь!
Просто бывает только в рекламе! Ну ты понял в какой.
Тебе нужно разместить тестовое веб-приложение на локальном веб-сервере.
npm i tiny-server --save-dev
package.json
добавь команду start
в раздел scripts
для запуска сервера: "scripts": {
+ "start": "tiny-server",
}
npm start
npm install
?scripts
?
npm start
— это зашитая команда в NPM
Можно запускать команду не только npm run start
, а короче npm start
Веб-сервер готов, нужно скачать тестовое приложение с GitHub.
npm i node-wget --save-dev
apps
в корне проекта.npx wget -d apps/ https://open-tutorials.github.io/cypress/apps/tesla.html
~/apps/tesla.html
apps/tesla.html
~
— так обозначается путь до корневой папки проекта.
~/apps/tesla.html
?npx wget -d google.html https://google.com/
google.html
, что там?Нужно открыть тестовое приложение в Cypress.
~/cypress/integration/best-selectors.spec.js
it('should do register user', () => {
cy.visit('http://localhost:3000/apps/tesla.html');
});
npx cypress open
best-selectors.spec.js
Нужно ввести в поле фамилия тестовые данные.
it('should do register user', () => {
cy.visit('http://localhost:3000/apps/tesla.html');
cy.get('#b1h7e4i8d3').type('Иванов');
});
Селектор поля меняется 🥴 динамически при каждом запуске приложения.
❗ Следует использовать устойчивые к изменениям селекторы!
🙅 Анти-паттерн
Использовать хрупкие селекторы, которые могут быть изменены.
Пример — хеш элемента который может поменяться после новой сборки приложения:
<button id="zIyPEZ0bf">Продолжить</button>
👍 Лучшая практика
Добавить специальные
data-
атрибуты к элементам в HTML разметку.
<button data-cy="register">Продолжить</button>
В твоем тесте ты напишешь:
cy.get('button[data-cy=register]').click();
❗ Тестируй только то, что можешь контролировать! ~"В конспект"
🙅 Анти-паттерн
Пытаться тестировать сайт или приложение, которое ты не контролируешь.
👍 Лучшая практика
Работать совместно с разработчиками сайта или приложения.
Если ты не контролируешь приложение, то можешь столкнуться с проблемами:
❓ Это хорошие селекторы?
body > :nth-child(1) > :nth-child(4)
#k9b1c2e4b1 > [data-cy="reset"]
- [ ] Отличные
- [x] Плохие
Это плохие селекторы, встроенный selector playground в Cypress не справляется — в топку 🤮
Всегда ищи селекторы через Инструменты разработчика в Chrome
В окне тестового приложения:
С помощью тэгов HTML и стилей CSS рендерится пользовательский интерфейс.
// first name input field on registration form
cy.get('form.registration input[name=first_name]')
Нужно написать позитивный тест-кейс зарегистрироваться с шагами:
Нужно найти уникальный семантический (со смыслом) атрибут или класс.
<input>
внутри одной формы атрибуты name=xyz
являются уникальными.<button>
атрибут type=reset
и type=submit
определяет семантику действия.В нашем случае для поля Имя это input[name=first_name]
$('input[name=first_name]')
и нажмите ENTER ↵
cy.get('input[name=last_name]').type('Иванов');
cy.get('input[name=first_name]').type('Иван');
$('input[name=email]')
— cелектор для поля Email не уникален!
На странице 2 формы Регистрация и Вход и на каждой из них есть поле Email.
Контекст для элемента: форма, группа, раздел — некоторая уникальная область интерфейса.
<form>
, <fieldset>
, <header>
, <footer>
, <nav>
т.д.<div>
, <span>
, <p>
с семантическими атрибутами или классами.Примеры хороших 👍 контекстов:
aside[data-type=left]
— ищем боковую панель слева.form.registration
— маловероятно, что на одной странице 2 формы регистрации.#registration
— уникальный ID элемента..registration
— семантически класс registration
уникален.[data-type=registration]
— специальный data-*
атрибут добавленный разработчиками..app-header .app-userbar
— префикс .app-*
в имени класса делает элементы уникальными.Примеры плохих 🙅 контекстов:
aside
— в приложении может быть 2 панели: справа и слева.form
— на одной странице может быть несколько форм..header
— семантически класс не уникален.fieldset[name=credentials]
— на форме могут быть 2 формы с одинаковой группой полей.🔥 Необходимо добавлять контекст к селекторам элементов!
Примеры хороших 👍 селекторов с контекстами:
form.registration input[name=first_name]
— конкретное поле на конкретной форме.form[name=registration] button[type=submit]
— кнопка с конкретным поведением на форме.form[name=registration] button.register
— уникальная кнопка на форме.aside[data-type=left] .menu a[href="/register"]
— в левой панели в меню ссылка на конкретный адрес.Примеры плохих 🙅 селекторов с контекстами:
form.registration input[type=text]
— полей с типом текст может быть много.form[name=registration] button
— что делает кнопка?Элементы в Cypress можно находить еше по текстовому содержимому тегов.
cy.get('form.login button[type=submit]')
на cy.contains('Войти')
lang=en
в URL:cy.visit('http://localhost:3000/apps/tesla.html?lang=en');
Мини-тест. Это хороший селектор?
cy.get('input[placeholder=Имя]').type('?');
- [ ] Да, конечно
- [x] Нет, нет, нет
Неееет! Это тоже самое, что и с `contents`
**При смене языка, тест перестанет работать!**
<iframe src="https://giphy.com/embed/wYyTHMm50f4Dm"
width="480" height="277" frameBorder="0" class="giphy-embed" allowFullScreen></iframe>
❗ Используй селекторы устойчивые к изменениям конфигурации приложения.
❗ Что делать, если нельзя найти хороший селектор:
data-cy
Текущая разметка:
<body>
<div>
<footer>
<p>Все права защищены</p>
</footer>
</div>
<body>
В твоем тесте:
it('should do check copyrights', () => {
// TODO: should be p[data-cy=copyrights]
// we can use contains
cy.contains('Все права защищены').should('be.visible');
// or exact hierarchy
cy.get('body > div > footer p').should('have.text', 'Все права защищены.');
});
~/apps/tesla.html
и добавь data-cy
аттрибут:<body>
<div>
<footer>
<p data-cy="copyrights">Все права защищены</p>
</footer>
</div>
<body>
cy.get('footer p[data-cy=copyrights]').should('have.text', 'Все права защищены.');
Названия аттрибутов для целей тестирования могут быть разными:
data-for-test
,data-ui-id
,data-test-id
и т.д.
Та да 🥳 Ты дошел до конца.
Найди лучшие селекторы для формы регистрации и заполни ниже:
Полезный материал?
* 🤩 Очень полезный материал
* 😃 В целом полезный
* 😐 Возможно что-то пригодится
* 😒 Нет ничего полезного
* 😬 Абсолютно бесполезно
**Спасибо за ответ!**
Все ли было понятно?
* 🤩 Все понятно на 100%
* 😃 В целом все понятно
* 😐 Что-то понятно, что-то нет
* 😒 Понял только малую часть
* 😬 Ничего не понял
**Спасибо за ответ!**
Как тебе такой формат туториала?
* 🤩 Очень удобно
* 😃 Мне понравилось
* 😐 Нормально
* 😒 Не удобно
* 😬 Ужасно
**Спасибо за ответ!**