Что нового
  • Что бы вступить в ряды "Принятый кодер" Вам нужно:
    Написать 10 полезных сообщений или тем и Получить 10 симпатий.
    Для того кто не хочет терять время,может пожертвовать средства для поддержки сервеса, и вступить в ряды VIP на месяц, дополнительная информация в лс.

  • Пользаватели которые будут спамить, уходят в бан без предупреждения. Спам сообщения определяется администрацией и модератором.

  • Гость, Что бы Вы хотели увидеть на нашем Форуме? Изложить свои идеи и пожелания по улучшению форума Вы можете поделиться с нами здесь. ----> Перейдите сюда
  • Все пользователи не прошедшие проверку электронной почты будут заблокированы. Все вопросы с разблокировкой обращайтесь по адресу электронной почте : info@guardianelinks.com . Не пришло сообщение о проверке или о сбросе также сообщите нам.

E2E testing in React with Cypress

Lomanu4

Команда форума
Администратор
Регистрация
1 Мар 2015
Сообщения
1,674
Баллы
155
Introduction


In the

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

from september, I wrote about how to set up Cypress to enable end-to-end testing in React, demonstrating two ways to run the tests (through the interface and via the terminal). Now, the idea is to show how the testing works, along with some concepts and examples.

Tests structure


The test structure follows this format:

  • describe: represents the test block to be executed, which can refer to a specific context or flow
  • it: represents the test to be run, following these steps
    1. access the page where the test will start
    2. search an HTML element on the screen
    3. interact with the element
    4. define an assertion for the test

describe("Block description", () => {
it("test description", () => {
access the page
search for an element on the screen
interaction with the element

test assertion
})

it("another test description", () => {
(…)
})
})

Here's an example of a search, an element interaction and an assertion inside the test, but it's possible to perform multiple ones inside it.

Access the page


To access a page, cy.visit() will be used, which allows navigating to a URL that will serve as the starting point for the tests.

Search for an element on the screen


There are various ways available for searching HTML elements. Here are some examples:

QuerySearchCode
containsby textcontains(text)
getby selectorget(selector)

The search using get can be done in various ways:

SearchExample
by data-cycy.get('[data-cy="example"]')
by namecy.get('[name="submit"]')
by idcy.get('#main')
by classNamecy.get('.btn')
by rolecy.get('button')

The data-cy corresponds to a definition on the element that is exclusive for locating it in tests.

Interaction with the element


After locating the element on the page, it’s possible to interact with it. Here are some available ways:

InteractionAction
click()click
dblclick()double click
type()type a text
check()check checkbox/radio button
uncheck()uncheck checkbox
submit()submit a form
Test assertion


To define the test assertion should() will be used, which has an alias and(). Here are some available ways:

AssertionValidation
should('have.value', value)value
should('be.enabled')is enabled
should('be.disabled')is disabled
should('contain', text)text
should('have.length', length)length
should('exist')existence
should('include')inclusion

To validate the negation of assertions, not. can be placed as the first part inside should, for example should('not.exist').

Tests execution


In last month's article, linked in the introduction of this article, two ways to run tests in package.json were defined, via the interface and through the terminal:


{
"scripts": {
//...
"cy:open": "cypress open", // interface
"cy:run": "cypress run" // terminal
}
}

To run tests locally in Cypress, the application must first be started locally in one terminal and then run the tests in another terminal.
Since the same port is defined when the app is started locally, and to avoid always writing the same starting point in the first step of all tests (for example, starting from port 3000), it’s possible to define this in cypress.config.js:


const { defineConfig } = require('cypress')

module.exports = defineConfig({
e2e: {
baseUrl: '

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

',
},
})

This way, any test that starts with cy.visit('/') will be directed to the page

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

.
Observation: when running tests in testing environment pipelines, an ENV variable can be set in baseUrl to access the expected url associated with the environment where the tests will be executed.

Tests example


For the following examples, it will be used the sample page that Cypress itself provides:

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.


That will represent, for this article, the url corresponding to the application running locally in the terminal.
Since all examples will start from this url, it will be set as the baseUrl in cypress.config.js:


const { defineConfig } = require('cypress')

module.exports = defineConfig({
e2e: {
baseUrl: '

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

',
},
})

The idea is to provide simpler examples to demonstrate each step involved in writing tests. However, in practice, when Cypress is used for end-to-end testing validation, the test tend to be more complex and involve many more interaction inside them.

Presence test


In this first test, it will be checked if, after clicking a link on the Cypress example page, we arrive at the expected page (making an assertion on the url) and whether certain elements are present on the screen.
First, it will be placed the file inside the cypress/e2e folder, which is where Cypress looks for tests to execute, naming the file presence.cy.js:


describe('Presence tests', () => {
beforeEach(() => {
cy.visit('/')

cy.contains('get').click()
})

it('reach expected page', () => {
cy.url().should('include', '/commands/querying')
})

it('has queries options', () => {
cy.get('#querying').should('contain', 'get()')
.and('contain', 'contains()')
.and('contain', 'within()')
.and('contain', 'root()')
})
})

In this test block, the example Cypress page is accessed first, and then the link containing the text get is clicked. Since all tests in the block start the same way, this part was placed inside a beforeEach before the tests.
In the first test, it is expected that the page reached includes /commands/querying in the url, and in the second test, it is expected that the different available queries are displayed on the screen, validating by their text.

Running yarn cy:run in the terminal returns information about the test results, which I will break in parts for further explanation.
First, it shows the execution details, including the version of Cypress used, the browser, the version of node, the number of test files, and where they were retrieve from:


Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



Next, it displays the file that was executed, the test block, and the tests that were performed (with a positive indicator showing that the test passed), along with the total number of tests that passed:


Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



After that, a box is showed with the test results, including the total number of tests executed, how many passed, how many failed, how many were pending, how many were skipped, how many generated screenshots, whether a video was recorded, the duration of the tests, and finally, the executed file:


Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



Finally, there is a table displaying the executed file, execution time, number of tests, how many passed, how many failed, how many were pending and how many were skipped. Since all tests passed, it shows the message All specs passed!:


Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



Another way to run tests is via the interface, following those steps:

  • Run yarn cy:open
  • Select the E2E Testing box
  • Choose your preferred browser
  • Click on Start E2E Testing
  • Click on the file you want to execute
  • Wait for the tests to execute


Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



During execution, the navigation will be displayed on the right side according to the tests.
Once the execution is complete, the executed test block and the tests will appear on the left side. In this case, since they passed, there will be a positive indicator next to them. On the right side, the point where the execution stopped will be shown:


Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



On the left side, you can open one of the tests and hover over each part that was executed inside the test to see on the right side where you were during the navigation:


Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



Now, simulating a failure in the second test of the block by modifying one of the assertions, running it through the terminal will show some differences in the result display.
The test inside the block that failed will be highlighted in red, indicating that one test passed while another failed, along with the specific point where the failure occurred:


Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



The results section will be highlighted in red, indicating that one test failed and that a screenshot was taken showing what the screen looked like at the moment of the failure:


Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



Finally, a table will display that out of two tests, one passed and one failed, with a red highlight at the bottom stating 1 of 1 failed (100%). This information refers to how many test blocks failed, not the individual tests themselves. Since the Presence tests block had one test failing inside it, the entire block is considered to have failed:


Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



In the case of execution via the interface, it will show specifically where the test failed, with the image displayed alongside it:


Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



Multiple interactions test


In this test, after clicking the type link on the example Cypress page, it will be verified if the expected page is reached (by asserting the url), and after entering text into an input field, it will be checked whether the value inside it matches what was written.
The file will be placed inside the cypress/e2e folder, which is where Cypress looks for tests to execute, naming the file actions.cy.js:


describe('Actions tests', () => {
beforeEach(() => {
cy.visit('/')

cy.contains('type').click()
})

it('reach expected page', () => {
cy.url().should('include', '/commands/actions')
})

it('fill email address', () => {
cy.contains('Email address').next().type('example@aloha.com')

cy.contains('Email address').next().should('have.value', 'example@aloha.com')
})
})

In this test block, next() is used to access the HTML element immediately following the one that was searched. This way, it’s possible to access the input field to fill it in, which is located after the searched title. After execution, the tests pass successfully.

Best practices


The Cypress documentation outlines best practices to follow during testing. I will present some of them below:

Define a global baseUrl


For tests that always start from the same domain, set the baseUrl in cypress.config.js:


const { defineConfig } = require('cypress')

module.exports = defineConfig({
e2e: {
baseUrl:,
},
})
Use beforeEach for shared code between tests


It is recommended to place shared code inside a beforeEach:


beforeEach(() => {
// shared code
})
Make multiple assertions together


Instead of separating assertions into different tests for the same element, make multiple assertions:


// Not recommended
it('has get query option', () => {
cy.get('[data-cy="queries"]').should('contain', 'get()')
})

it('has within query option', () => {
cy.get('[data-cy="queries"]').should('contain', 'within()')
})

// Recommended
it('has queries options', () => {
cy.get('[data-cy="queries"]').should('contain', 'get()')
.and('contain', 'within()')
})
Element Search Priority


This can be somewhat controversial, as the main suggestion is to add a unique test locator element inside the HTML element. Starting from the following component:


<button
id="example"
class="btn-primary"
name="submission"
role="button"
data-cy="primary"
>
Submit
</button>

Below is the increasing order of priority and the reasons presented in the documentation:

SelectorRecommendedReason
cy.get('button').click()NeverWorst - too generic, no context
cy.get('.btn-primary').click()NeverBad. Coupled to styling. Highly subject to change
cy.get('#example').click()SparinglyBetter. But still coupled to styling or JS event listeners
cy.get('[name="submission"]').click()SparinglyCoupled to the name attribute which has HTML semantics
cy.contains('Submit').click()DependsMuch better. But still coupled to text content that may change
cy.get('[data-cy="primary"]').click()AlwaysBest. Isolated from all changes
Conclusion


The idea of this article was to provide an overview of how testing works, covering structure, page access, HTML element search, interactions, and validations, along with examples and best practices recommended by the documentation. However, there are many other testing scenarios and ways to use Cypress. For this reason, I am providing the main links categorized by topic for those who want to delve deeper.

Links



Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.




Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

 
Вверх