Testing a JS app in 2019
Why should I tell you this story?
The ecosystem has continued to evolved presenting new test runners, test frameworks or assertion libraries all the time. For the past few years I’ve been very happy with the maturity of the platform, but it still pushes forward. And that makes me, as a developer, very happy.
How can I test feature A?
Well the answer is always: “It depends...”
Let me instead try to explain every tool or type of test I currently try to uphold.
Static type checking
ESLint have a broad range of rules you can specify to enforce code quality.
To make sure every developer uses the same code formatting I have also added prettier to the toolbox, which is run automatically using husky
The classic unit test
The smallest piece of testable code should be tested using a unit test. For this I currently use jest as my go-to tool.
These tests are simple to write and I always try to separate complex functionality inte testable pieces.
In client applications nowadays we tend to produce a lot of components. I write mine as React components and try to keep my components as ”unintelligent” or “pure” as possible. As it turns out pure components require fewer tests. To be able to tests my react components i use enzyme, which will let me verify the behavior of my component with different inputs.
Interacting with Components
Enzyme has two different major modes of testing your components. The first one - the shallow mount - let’s me run isolated tests of only the component under test, which will mock every other component in the component tree.
Integrating 2 Components
The other major mode of enzyme is the full mount which will also include other components in the render tree. This will allow you to mount two or more components and let them integrate in a controlled way.
During development there exist tools that will help you as a developer to focus on just one component at a time. Storybook is a tool that quickly will let you describe how your component could be used and what they will look like using different variants of inputs.
It will render your components in a browser and will let you both verify the visuals of your component as well as interacting with it.
Visual regression testing Components
Since I already have all my Components defined in storybook, I might as well take full advantage of it. That is why I also use a selection of storybook add-ons. On of them is storyshots that runs visual regression tests using puppeteer against all my components. This will ensure that even minor changes to the visuals of my components will always require a verification.
A side note of using visual regression tests is that it also simplifies the Pull Request process since you always get the updated snapshots as images. Which
A modified component triggers a diff image. The original image on the left. The updated on the right. And a pixel-by-pixel diff in the middle.
Cypress will let you verify that your entire application works as expected. It will let you navigate and interact with your app and verify the behavior.
A good test always gives reproducible results. Every time! But since I’ve added the storyshot and cypress to my test suite I also had to expand the use of docker containers to make sure that the results are reproducible between different developer workstation as well as the CI pipeline.
So, do I always add tests on all levels for all my components?
No, I don’t. That would increase the cost of maintaining the tests, which is not desirable.
What areas are not covered by by the current set of tools in my toolbox?
In short every touch-point towards a service or API that is outside of my control. Instead of writing tests I make sure to verify the input as early and as well as possible.
My tools that help me write better code as of 2019 are: