How to include API testing in frontend regression
When you’re combining automation and manual testing, software testing may seem like a tedious task. But today we are sharing some pro tips from our finest so that you can always #BeTechReady.
Verche is our QA engineer who started as an Intern and today plays a crucial part in the team. Involved in automation testing, as well as, mentoring new members of the team and helping them become a part of the team, she is the one that makes sure that all bugs are handled.

Bugs caused by frontend misrepresenting the backend data or by invalid or partially invalid requests or even lack of communication between the developers are more often than not reported by the clients who caught them in production. Everyone in software development knows that the later you find the bug that more cost it infers. Most of the companies that do have automation testing often split the QA teams on the technical level so part of the team tests the frontend and the other part of the team tests the backend. This will allow this kind of issues to pass unnoticed by the QA team. To remedy this, our QA team which I am a part of, started to use a new strategy for testing the frontend. We decided to include API testing in our frontend regression tests. This allows us to better cover the backend API by both, frontend and backend regression and additionally verify that the logic in our frontend application is correct.
There are two ways you can implement this kind of strategy in your project. The two ways directly depend on the testing framework you use. For our purpose, we will use Cypress as an end-to-end testing framework. The first way is to listen to the network requests and responses i.e. the communication between the backend and frontend and do assertion based on the actual data. The second way is to call the backend directly with the correct request and assert that what is shown on the frontend corresponds to the data returned by the backend. This strategy can only be used for end to end testing because when testing with mock data defeats the purpose of the assertions. In the following chapters, I will go into more details on how to implement each part in your frontend end-to-end regression tests.
Listening to backend-frontend communication
How to implement:
- .intercept() the targeted request and capture its data
- assert that frontend correctly presents the captured data
The right time to make an interception of specific request is before the request appears in network. Or, we can simply intercept the request before navigating to the actual site. We must call .intercept() before the API request is invoked for Cypress to be able to save its data. Then, we wait the API call to be invoked and finished before continuing. You can read more about .intercept() command here.
it('test intercept()', function () { // intercept the request and safe the rest data as variable cy.intercept('/rest').as('apiData'); // visit a your site URL cy.visit('https://example.com/'); // wait for the API call to finish and extract response body cy.wait('@apiData').its('response.body').then(res => { // save POM element as specified variable name page.getElementName('frontend'); // get element by name cy.get('@frontend').then(data => { // do assertion on data expect(res.property).to.equal(data); }); }); });
Getting data directly from backend
How to implement:
- Make a .request() to get the actual data that needs to be presented on the frontend
- assert that frontend correctly presents the captured data
This command allows us to invoke a particular API call directly from Cypress and save its result. This will bypass the need for interception of the request, but can also introduce flakiness in our tests when we deal with fast-paced changes of the data. This method will provide data whenever it’s needed ignoring actual API calls done by your frontend. You can read more about .request() command here.
it('test request()', function () { // send request to backend cy.request('/rest').then(response => { // save POM element as specified variable name page.getElementName('frontend'); // get element by name and do assertions cy.get('@frontend').should('equal', response.body.property); }); });
Note: This is not limited to HTTP calls, but can also be used let’s say with a database query, for example with using mysql node library.
New world of assertions
With access to the actual data that needs to be shown on the frontend, a lot more assertions can be done that previously couldn’t be implemented. Those who cover a lot of topics, some of which are performance testing, sorting and filtering tests and similar, could find this very useful. This will help you implement complex test cases and will help both the frontend and the backend developer teams. For example, you can assert that no additional calls are done to the backend when they are not necessary which will, in turn, reduce the load and improve stability. Here are some of the simple assertions you can do of the top of my head:
- Assert that all data is present on frontend
- Assert that when using pagination frontend represents the correct data
- If the API supports sorting assert that the actual order does not break on frontend
- When API support filtering assert that frontend removes data from previous filter
- Assert that backend doesn’t return error when it is not expected
- Assert that validations which can be done on the frontend are not propagated to the backend
- Assert that when the backend API supports filtering if the filter is not changed frontend doesn’t sends additional requests
- Assert that when the backend API supports sorting if the sorting is not changed frontend doesn’t sends additional requests
Conclusion
Implementing this kind of additional assertion does require a lot of work but the investment is well worth it when testing complex applications. This kind of testing will save you from additional manual testing, will help you trust your application more, will make the final product better and clients happy which is always the end goal. We’ve covered two ways to implement this testing strategy with Cypress. I suggest using the first method whenever possible as it provides more accurate results and faster tests. The second method is more suitable for beginners and scenarios when you can’t intercept communication between frontend and backend, such as websocket or SSE(Server-Sent Events) communication. The important note is that if the development is fast-paced, it can be hard to keep up with all the changes. I hope that I showed you a way to improve your process, the quality of your application and at least look at frontend testing from a different perspective. Happy testing!
Thank you Verche for all the tips and tricks you shared and helped us #BeTechReady for anything. 😉
If you like a challenge and can meet frequent and tight deadlines, you are at the right place. Check out our Career page and learn more about all the available positions and maybe you will be the author of the next #BeTechReady!