Front-end Testing: Static vs Unit vs Integration vs E2E

Mateusz Wójcik

Jul 20, 20205 min read

Front-end Testing: Static vs Unit vs Integration vs E2E

Table of Content

  • What is static testing?

    • Static testing with ESlint

    • Static testing with Typescript

  • Front-end unit testing

  • Front-end testing: the integration tests

  • Front-end testing: End-to-End tests

  • Last words on front-end testing

Front-end testing is a big part of development. The benefits of adding tests to our apps are clear, but it can be confusing. There are a lot of test types, and their definitions may vary depending on who you ask, the tools you use, and the ways we can test code. The internet provides a few examples of "roadmaps” for testing front-end, like the testing pyramid or the testing dorito. But the Testing Trophy by Kent C. Dodds is the one that caught my eye. Let’s go through each segment of this testing trophy and see its pros and cons.

What is static testing?

Static tests should be the base of front-end testing. They consist of linters (e.g. ESlint) and static type checking (e.g. Typescript).

Static testing with ESlint

You may already be familiar with ESlint as it's trendy in the Javascript ecosystem. It's a tool that scans your code and finds potential problems in it; for example, you are trying to use a variable you didn't declare yet, or maybe you didn't import a function, but you are still trying to run it. ESlint can automatically fix some of these problems. It's easy to configure, and there are already existing configs to help you get up and running, like eslint:recommended or eslint-config-react-app. 

Installing the required packages takes only a few minutes. It's a good idea to tweak your IDE to run ESlint on every save or to use some tools like Husky and Lint-Staged to run it on every commit. This way, you make sure that every line of code that goes into a remote repository is checked and hopefully fixed by ESlint.

Static testing with Typescript

Typescript, on the other hand, requires a little bit more work. This is because it is a superset of Javascript that can extend JS capabilities. We are talking mostly about static type checking, which is available in a lot of programming languages but unfortunately not in JavaScript. 

It allows you to set the type of variable or function parameters. For instance, in a function function 

sum(a: number, b: number): number { return a + b; }

we specify that the parameters 'a' and 'b' should be numbers, and that our function will return a number.

In this example, we are saying that the parameters "a" and "b" should be numbers and also that our function will return a number. So whenever you try to pass a string as a function argument, Typescript will catch it and throw an error. Using Typescript is the most challenging part of static testing as it requires developers to learn some new syntax.

Front-end unit testing

Unit tests are pretty simple because their focus is to test separated parts of the app. No external dependencies, no software frameworks. 

They can even test a single function. For instance, we can add a unit test for the function 'sum' as follows: 

test('sum function', () => { expect(sum(1, 3)).toBe(4); });

 In this test, we're expecting that the sum of 1 and 3 will result in 4.

Unit tests are pretty simple and can be read as standard English: "Expect that sum with arguments 1 and 3 will result in 4." According to the Testing Trophy, they are a good starting point for more complex tests. If you are interested in this kind of test, take a look at the Jest library. It doesn't require a lot of configs and generally works great, provided you have enough helpers to test everything you need. You can also create more complex test cases with mocking API requests and responses.

As part of your product development, you should focus on testing the crucial parts of the application as well as its logic. Otherwise, you might find yourself testing implementation details, and that's unnecessary. So far, your code is covered by static tests, and some parts of your app have their own unit tests. Let’s see the next type of tests, that is, the integration.

Front-end testing: the integration tests

Integration tests ensure that various parts of the app work together. They’re crucial from a business viewpoint. Remember that users don't care if a single function of your app works. They are interested in knowing if they can use the whole application, and that's where integrations tests shine. 

The React Testing Library is a go-to resource for integration tests. Its main goal is to allow for testing the way your users will use the app and avoid testing implementation details. RTL offers a ton of utils to make testing more straightforward and more maintainable. 

Let's consider a simple React component. The component consists of a label connected with an input field, a button to show a message, and a paragraph element to display the message. The label is tied to the input field through the 'htmlFor' property, and the button has an onClick event handler that changes the state of the message.

This simple component consists of a label connected with its input, a button to show the message, and a paragraph in which we will display it.

Now let's add a test for it: we first render the component, select the elements we need to interact with or inspect, simulate user input and button click, and then check if the expected message shows up in the paragraph. This test would look something like this:

test('user interaction test', () => {
    const { getByLabelText, getByText } = render(<MyComponent />);
    const input = getByLabelText('message-input');
    const button = getByText('Show Message');
    const messageContainer = getByText('');
    fireEvent.change(input, { target: { value: 'Hello World' } });;
    expect(messageContainer.textContent).toBe('Hello World');

Let's go through this example:

1. We import a few helpers provided by RTL alongside the component to be tested.
2. We create a new test and name it.
3. We use the render method from RTL to render the component. This method provides so-called queries that will let us select the elements needed in the test.
4. We use the provided queries to select the input, the button, and the paragraph where the message is displayed. We can choose the elements in different ways even when they show up asynchronously, and we can use regexp (like here, case-insensitive). The most interesting is "getByLabelText" because we can select the input by first choosing the label connected to it. We can also check if our inputs are accessible.
5. There shouldn't be any message in it, so we test for that.
6. We are using a helper to simulate the user’s input.
7. We simulate another event: click on the button.
8. We add another expectation to see if the message container contains the provided value.

Hopefully, our test passes!

Front-end testing: End-to-End tests

The last part of the Testing Trophy is End-to-End tests. E2E tests are different from other types of tests because they run in a real browser. We write test cases as step-by-step instructions for the automated browser to go through the parts of the app we want to test. 

One of the most popular tools for End-to-End tests is Cypress. It's easy to set up and to use, on top of being fast. 

Here's an example of an end-to-end test for a registration form using Cypress:

it('tests user registration', () => {


    cy.url().should('include', '/login');

In this test, we navigate to the registration page, fill in the username and password fields, click the register button, and then check if we're redirected to the login page.

1. We create our test
2. We tell Cypress to visit the URL with the registration form.
3. We take proper inputs and type some values.
4. We look for a button with a "Register" text, and we click on it
5. After successfully registering, we should be redirected to the "/login" page, so we test for that.

When we run this test, a browser window pops up, so we can see the test runner perform each step. If something goes wrong, Cypress lets us know.

Usually, End-to-End tests take longer to write than the unit or integration tests. They also take longer to run as they communicate with a real API, so you should only write them for the most critical flows in the application.

Last words on front-end testing

The Testing Trophy is a great guideline. We can start with static tests, then move on to unit tests, and finish with integration tests. We can leverage the power of end-to-end tests to automate the testing of the app’s most critical routes. Drop us a line to learn more about front-end testing or write to

Don't miss a beat - subscribe to our newsletter
I agree to receive marketing communication from Startup House. Click for the details

Published on July 20, 2020


Mateusz Wójcik JavaScript Developer

You may also highlightlike...

14 accessibility hacks to make your users’ day better
AccessibilityUX designFront-end development

14 accessibility hacks to make your users’ day better

Accessibility in app development is often overlooked, but it plays a vital role in ensuring inclusivity and improving user experience for individuals with disabilities. With approximately one billion people worldwide experiencing some form of disability, it's crucial to consider accessibility as a necessary aspect of app design and development. By incorporating accessibility features from the beginning, you not only cater to a significant user base but also create a more user-friendly and inclusive app for everyone.

Maciek Kozłowski

Dec 02, 20197 min read

Why do we love using Gatsby and Strapi for building websites?
Next.jsStrapiFront-end development

Why do we love using Gatsby and Strapi for building websites?

Static site generators (SSGs) and headless content management systems (CMSs) have gained popularity for creating fast, performant, and easily editable websites. By combining the power of Gatsby, a React-based static site generator, with Strapi, a flexible headless CMS built with Node.js, developers can create blazing fast websites that offer seamless content management. This article explores the concept of static sites, the role of CMSs, and how Gatsby and Strapi work together to deliver swift, customizable, and user-friendly web experiences.

Mateusz Wójcik

Feb 21, 20205 min read

What Does a Test Written with Test-Driven Development Represent: Unpacking the Benefits and Pitfalls of TypeScript
Software developmentFront-end development

What Does a Test Written with Test-Driven Development Represent: Unpacking the Benefits and Pitfalls of TypeScript

TypeScript, an open-source language developed by Microsoft, offers numerous benefits for software developers, including static typing and reduced errors. However, it also comes with trade-offs to consider. This article explores TypeScript's advantages, its suitability for large projects, how it reduces errors, and its compatibility with JavaScript.

Marek Majdak

Jul 18, 20235 min read

Let's talk
let's talk

Let's build

something together


We highlightbuild startups from scratch.

Startup Development House sp. z o.o.

Aleje Jerozolimskie 81

Warsaw, 02-001

VAT-ID: PL5213739631

KRS: 0000624654

REGON: 364787848

Contact us

Follow us


Copyright © 2023 Startup Development House sp. z o.o.

EU ProjectsPrivacy policy