Restructuring Frontend Testing Pyramid: alternative to Unit/Integration/E2E approach
Tags: testing, javascript, productivity, webdev
Published: 2022-03-20 16:03:57

Many web developers prefer to use such traditional terminology as **Unit / Integration / End-to-End testings** in their projects as these terms are still so familiar in the old-school software engineering fields. 

But shall we keep using these distinctions when component-oriented frontend frameworks are so predominant nowadays?

Let me compare the old-school testing pyramid with the new pyramid and prioritize testings based on cost performance.

**The old-school testing pyramid**
![New Frontend Testing Pyramid](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a59r7l4g8fm95n9moedv.png)

- **Unit Tests:** The meaning of "Unit" is so ambiguous in the context of frontend development. Does it mean testing a UI component, or a bigger component like a todo table, or even an individual page? Many people readily imagine different things, especially for those who are from backend and infrastructure teams.

- **Integration Tests:** Again, The meaning of "Integration" is also unclear for the frontend development. Does it mean interactions among components or data consistency across pages?

- **End-to-End Testing:** It is hard to tell from what end to what end people are talking about. 

## The restructured frontend testing pyramid

Let me reconstruct the frontend testing pyramid based on the test types and their priorities for modern framework development.

![New Frontend Testing Pyramid](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5y1ipmh3te6h6pqvwcop.png)

I also prepared the table version with classic testing names.

![Testing Table](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pylobvvttv8qain7wq49.png)

### Code Quality Checks 

The naming of "Static Testing" makes sense by itself, but what it actually does is analyze code in the repository and identify poorly written code. 

![Linter Check](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t59mqia757s852tjv5sn.png)

There is no doubt that this test produces the most significant value for the cost. All developers need to do is just add syntax rules ([ESLint](https://eslint.org/)) and format rules ([Prettier](https://prettier.io/)) at the beginning of the project. _Javascript and even Typescript are innately susceptible to runtime errors_, but enforcing these coding rules in the build process amazingly captures most coding errors in the compile errors like Java or Golang.

### Interaction & Scenario Testing

What developers call "Integration Testing" in the frontend context consists of two types of testing - interactions and scenario.

Interaction testing is to ensure the quality of interactive features in a specific page, such as data binding in radio buttons, click events, and input validations. 

Scenario testing is to secure data consistency and transitions across pages. For example, an online shopping experience comprises views from the search page, product page, cart page, checkout page, and a thanks page. Aside from testing each interactive feature, it is valuable to guarantee that users can accomplish a typical shopping experience.

I highly prioritize Interaction and Scenario Testings to Logic (Unit) Testing because focusing on actual user experience solves the most problems users would face and most errors found in Logic Testing can be covered by Interaction and Scenario Testings👍

There are a few automation tools for these purposes, but my recommendation at this moment is [Cypress](https://www.cypress.io/), which is battle-tested and easy to start.

![https://docs.cypress.io/guides/getting-started/writing-your-first-test](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7a6ltrlt5n355zyxmt6r.png)

### Performance Testing

This name is already self-explanatory, and developers just need to run [Lighthouse](https://developers.google.com/web/tools/lighthouse) or its [CI](https://github.com/GoogleChrome/lighthouse-ci/blob/main/docs/getting-started.md) to kickstart. Typical performance tools check speed, SEO, accessibility and other best practices for web.

These optimizations are usually easier to handle in the middle or the end of the project. Thus, I set the performance testing to a lower priority.

![Lighthouse Score](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9o95wo2n8mp0x2gzrouh.png)

### Logic Testing

Some components or functions have complex rules in them, thus, testing its logic (by tools like [Jest](https://jestjs.io)) makes sense. This is part of the Unit Testing, but the name sounds too ambiguous, as explained before. 

Rather than intensively testing logic, it is wiser not to bring and develop complex rules to the frontend development in the first place. Only acceptable are presentation logics, and backends should handle all complicated logic for the applications.

### Visual Testing

Many developers call "UI Testing" but Visual Testing sounds more evident for checking component and page stylings.

I put this testing to the lowest priority but it depends on project goals. In my case, stylings are more robust under the scoped-component development with React/Vue and the Inverted Triangle CSS architecture. 

In large projects, developers are encouraged to collaboratively work with UI designers and exchange opinions about component and page stylings with tools like [Storybook](https://storybook.js.org/).

## Conclusion

I emphasized the following points in this article:
- Explicit testing names compared to the old-school testing names
- More priority on interaction and scenario testing based on cost performance
- Automation Tools for each testing

I hope this article was helpful to other developers!