В последнее время на работе я устал писать код, который в итоге попадал в кодовую базу в стиле «спагетти». Мой код, вероятно, также внес бы негативный вклад в эту кодовую базу.
Основная проблема заключалась в культуре компании. Поэтому в последний период я решил сменить работу. Стать фронтенд-разработчиком в компании, где «ценность» находится в центре всего.
И вот я написал один из своих первых тестов на Cypress.
Тесты дают нам надежность и безопасность, принося много пользы. К сожалению, это не всегда сразу воспринимается клиентами или компаниями, в которых человек работает. Часто они воспринимаются как пустая трата времени. Но они являются долгосрочной инвестицией.
С помощью Cypress мы можем писать e2e-тесты, которые позволяют нам проверять функциональные свойства и нефункциональные свойства, такие как производительность или надежность. Мы можем изучить потоки нашего приложения и убедиться, что все работает так, как мы задумали.
Ниже я покажу пример теста, сделанного с помощью Cypress на проекте React с NextJS.
Мы устанавливаем Cypress на нашу кодовую базу. Я буду использовать yarn.
yarn add cypress -D
Добавляем Cypress в поле package.json
scripts:
"cypress": "cypress open"
Чтобы мы могли запускать его в нашем CLI.
yarn cypress
Мы выбираем E2E тестирование
Вы можете просмотреть сгенерированные примеры и написать свой первый тест.
Если мы используем typescript, то в папку cypress нашего проекта добавляем файл tsconfig.json
:
{
"compilerOptions": {
"target": "es5",
"lib": ["es5", "dom"],
"types": ["cypress", "node"]
},
"include": ["**/*.ts"]
}
Теперь давайте напишем тест, который имитирует добавление товара в корзину и его проверку.
/// <reference types="Cypress" />
export {};
context('Step checkout', () => {
const mockObjectForm = {
email: 'test@test.com',
name: 'Pippo',
surname: 'Pluto',
address: 'Via Test',
city: 'Palermo',
province: 'PA',
zip: '90100',
phone: '123456789',
};
it('should fill the checkout form and complete the order', () => {
cy.stepSelectProduct();
cy.fillFormCheckout(mockObjectForm);
cy.get('[type="radio"]').check('wire_transfers');
cy.contains("Conferma l'ordine").click();
cy.get('.checkout__success__title')
.should('be.visible')
.scrollIntoView({ duration: 500 })
.contains('Il tuo ordine è stato ricevuto');
});
});
cy.stepSelectProduct()
и cy.fillFormCheckout(mockObjectForm)
— это команды, определенные в файле cypress/support/commands.ts
.
Мы можем рассматривать их как отдельные функции, которые будут вызываться по мере необходимости.
Первая из них имитирует выбор товара и добавление его в корзину. Вторая — для заполнения формы адреса доставки.
/// <reference types="cypress" />
declare global {
namespace Cypress {
interface Chainable {
fillFormCheckout(value: PersonalInfo): Chainable<Element>;
stepSelectProduct(): Chainable<Element>;
}
}
}
export type PersonalInfo = {
email: string;
name: string;
surname: string;
address: string;
city: string;
province: string;
zip: string;
phone: string;
};
Cypress.Commands.add('fillFormCheckout', (personal: PersonalInfo) => {
cy.get('input[name="customerEmail"]').should('be.visible').type(personal.email);
cy.get('input[name="policyConsent"]').should('be.visible').check();
cy.get('input[name="shippingAddress.firstName"]').should('be.visible').type(personal.name);
cy.get('input[name="shippingAddress.lastName"]').should('be.visible').type(personal.surname);
cy.get('input[name="shippingAddress.line1"]').should('be.visible').type(personal.address);
cy.get('input[name="shippingAddress.city"]').should('be.visible').type(personal.city);
cy.get('input[name="shippingAddress.stateCode"]').should('be.visible').type(personal.province);
cy.get('input[name="shippingAddress.zipCode"]').should('be.visible').type(personal.zip);
cy.get('input[name="shippingAddress.phone"]').should('be.visible').type(personal.phone);
cy.contains('Invia').click();
});
Cypress.Commands.add('stepSelectProduct', () => {
cy.visit('http://localhost:3000/');
cy.contains('Aggiungi al carrello').scrollIntoView({ duration: 500 }).click();
cy.contains('Carrello').click();
cy.get('a[href*="checkout.html"]').scrollIntoView({ duration: 500 }).click();
});
cy.visit
помещает нас на стартовую страницу.
Относительные get и contains используются для обращения к элементам DOM через классы и плейсхолдеры и имитации различных событий на странице через click()
и check()
.
Для ссылок на элементы рекомендуется использовать плейсхолдеры, поскольку они полностью отражают поток, который пользователь будет выполнять при заполнении формы или нажатии на кнопку.
Использование классов делает наши тесты более хрупкими. Мы должны писать тесты, которые ближе к пользователю, чем к разработчику.
В качестве альтернативы «get» можно использовать методы testing-library
, установив соответствующую библиотеку:
testing-library/cypress
Таким образом, мы можем использовать, например, cy.findByPlaceholderText('value')
вместо cy.get('input [name = "value"]')
.
Тест запустится автоматически при сохранении файла. Если наши тесты не длинные, мы будем использовать их чаще для тестирования новых возможностей, вводимых с каждой новой функцией или рефакторингом. Правильно создавать не слишком длинные тесты, и мы не обязательно должны достигать 100% покрытия.
До встречи 👋🏻
Спасибо, что прочитали ✨