Introduction of the importance of testing to raise a testing trophy for your front-end application.
I'm a front-end developer and I work in a web agency. I love this job because I have the opportunity to develop many projects from scratch and therefore continuously learn new development concepts.
But I'm often working on 3 or 4 projects at the same time, so it's hard to keep up with each one of them.
Moreover, I lose a lot of time processing feedbacks made either by my product owner or customers. This could be avoided by making testing an essential part of the development cycle. It would allow us to avoid some tiny bugs which cost time to the developer, product owner and client. At the same time, it would help us detect side effects in our codebase caused by the development of new features. Ultimately, we want to avoid clients seeing regressions in the application at all cost!
Simply put, what are our problems:
Clients without a technical background often don’t get the importance of automated tests. They are keener to pay for features that have a visual impact. I understand this point of view, but I think testing our web and mobile applications is crucial because it's a small investment compared to the future earnings. The final user shouldn't undergo bugs and we shall guarantee the best experience possible.
So, I decided to give you a brief introduction of React application testing.
Static tests are performed without executing the code but just by reading it. This includes typing your code with TypeScript or Flow and linters like ESLint or other similar tools.
These helpers are easy and fast to set-up and allow you to catch typos and type errors continuously while developing the application.
According to Wikipedia, a unit test is
a software testing method by which individual units of source code, sets of one or more computer program modules together with associated control data, usage procedures, and operating procedures, are tested to determine whether they are fit for use.
Not clear, right?
To simplify, we are testing one function in isolation from the rest of the code. Doing so, if you have a function that is supposed to convert a timestamp into a duration, your test checks that you always receive a correct output when calling it. For this kind of test, the most commonly used library is Jest.
This sort of test is rather quick and suitable for testing functions but not an application as a whole.
Integration tests happens at a higher level. The idea behind it is to render one or several components, to simulate requests API (mocking) and check that components are working well together. It is the more important kind or test for an application because it ensures the global behaviour as well as the synergy between components. I think that it can be harder to apprehend than unit test because it's very hard to determine what we should be testing. It may also be time-consuming and rather hard to set up. The most commonly used combination of libraries for integration testing is Jest and React Testing Library.
End-to-end testing simulates the behaviour of a real user browsing through your app. It emulates clicks in order to test some flows (like login), which can be critical and generate some bugs. For a web agency like us, this sort of test speeds up the sprint review by product owner and clients, allows us to test feature like password reset and some flows developed during the first sprint and never tested ever since. Thus, it is very good for detecting regressions. E2E test is easy to set up but tedious to write and maintain. However, Cypress makes this process a lot more enjoyable.
The three most common forms of testing when it comes to automated testing are Unit, Integration and End-to-End.
Above is a combination of Martin Fowler testing pyramid and Google’s testing pyramid, put together by Kent C. Dodds. This pyramid shows these 3 common forms of testing with 2 metrics: the time to set-up and the cost (in terms of time and resources). At the top, the test (here end-to-end) is very slow and costs a lot to set up. And at the bottom, the test is faster to set up and costs fewer resources. So if we follow this method, mainly it is necessary to do unit testing and a few other tests.
But tools have changed beyond the assumption in Martin's original Testing Pyramid concept. Static test is very quick to set up and unit test should be used parsimoniously whereas Integration test is the main subject of testing react applications. Therefore, Integration tests should have a bigger spot in the diagram than Static and Unit Tests. Finally, E2E test is sparely used and reserved for specifics workflows. This is why Kent C. Dodds introduced the testing trophy.
"The Testing Trophy" 🏆— Kent C. Dodds 🔭 (@kentcdodds) February 6, 2018
- End to end w/ @Cypress_io ⚫️
- Integration & Unit w/ @fbjest 🃏
- Static w/ @flowtype 𝙁 and @geteslint ⬣ pic.twitter.com/kPBC6yVxSA
In this trophy we have a scale of cost, time and complexity. Here again, the more you climb up the trophy, the costlier and slower the tests are to write and maintain. Tests placed atop the trophy are more tedious to write but bring more confidence that everything works as expected.
This slide from the Testing React and Web Applications workshop by Kent C. Dodds recaps this idea.
Everything can be summed up by a simple tweet by Guillermo Rauch, Vercel CEO 👇
Write tests. Not too many. Mostly integration.— Guillermo Rauch (@rauchg) December 10, 2016
At Tymate, our back-end developers have been accustomed to integrating unit and integration testing into their development process for some time. But in the front-end, we had different issues to address. Unlike the APIs that can be tested endpoint by endpoint, the functionality of our applications often involves multiple interlocking logics, which are often themselves API-dependent. The Testing Trophy helped us a lot building our front-end testing policy without losing more time than necessary.
Have you also had to set up tests in your company from scratch? Do you have any tips to share?