E2E testing tools

In the last few chapters, we explored the benefits and types of testing, including an overview of E2E testing. The testing libraries we typically use to build test suites and make assertions rarely include E2E testing facilities, so it's necessary for us to find our own tooling for this. 

The aim of an E2E test is to emulate user behavior upon our application and to make assertions about the application's state at various stages of user interaction. Typically, an E2E test will test a specific user flow, such as user can register new account or user can log in and buy product. Whether we're using JavaScript on the server side or the client side, if we're building a web application, it will be hugely beneficial to carry out such testing. To do so, we need to use a tool that can artificially create the user environment. In the case of a web application, the user environment is a browser. And thankfully, there are a large number of tools that can either emulate or run real (or headless) browsers that we can access and control via JavaScript. 

A headless browser is a web browser without a graphic user interface. Imagine the Chrome or Firefox browser, but without any visible UI, entirely controllable via a CLI or a JavaScript library. Headless browsers allow us to load up our web application and make assertions about it without having to pointlessly expend hardware capabilities on rendering a GUI (meaning we can run such tests on our own computers or in the cloud as part of our continuous integration/deployment process).

An example of such a tool is Puppeteer, a Node.js library that provides an API to control Chrome (or Chromium). It can run either headless or non-headless. Here's an example in which we open a page and log its <title>:

import puppeteer from 'puppeteer';

(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com');

const titleElement = await page.$('title');
const title = await page.evaluate(el => el.textContent, titleElement);

console.log('Title of example.com is ', title);

await browser.close();
})();

Puppeteer provides a high-level API that allows the creation and navigation of browser pages. Within this context, using a page instance, we can then evaluate specific client-side JavaScript via the evaluate() method. Any code passed to this method will be run within the context of the document, and will, therefore, have access to the DOM and other browser APIs. 

This is how we're able to retrieve the textContent property of the <title> element. You'll have noticed that much of Puppeteer's API is asynchronous, meaning that we have to either use Promise#then or await to wait for each instruction to complete. This may be bothersome, but considering the fact that the code is running and controlling an entire web browser, it makes sense that some tasks are asynchronous. 

E2E testing is rarely embraced because it is perceived as being difficult. While that perception was accurate at one point, it is no longer so. With APIs like that of Puppeteer, we can easily launch our web application, trigger specific actions, and make assertions about the results. Here's an example of using Jest (a testing library) with Puppeteer to make an assertion about the text within the <title> element at https://google.com:

import puppeteer from 'puppeteer';

describe('Google.com', () => {

let page;

beforeAll(async () => {
const browser = await puppeteer.launch();
page = await browser.newPage();
await page.goto('https://google.com');
});

afterAll(async () => await browser.close());

it('has a <title> of "Google"', async () => {
const titleElement = await page.$('title');
const title = await page.evaluate(el => el.textContent, titleElement);
expect(title).toBe('Google');
});
});

Fetching a page, parsing its HTML, and producing a DOM that we can make assertions about is a very complex process. Browsers are incredibly effective at doing this, so it makes sense to utilize them in our testing process. After all, it is whatever the browser sees that will dictate what the end user sees. E2E tests give us realistic insights into potential breakages, and it's no longer hard to write or run them. They are immensely powerful for the clean coder especially, as they let us see the reliability of our code from a more user-oriented perspective.

As with many of the tools we've explored, E2E testing may be best integrated into our development experience via automation. We'll now explore this in brief.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.83.62