Principles for automated testing
In general, applications with good test coverage will be easier to run, fail less, behave more as expected, and have code that is easier to follow. At Gjensidige, we don't require a specific level of test coverage, but we strongly encourage you to have a healthy amount of tests for your web apps.
Purpose
Our general principles for building web applications are relevant for all front-end development at Gjensidige. They are broad, and when it comes to testing we felt it needs a page of its own. See them as a guide. And please discuss them with us on Slack at #frontend.
If you see the need, feel free to add your own team principles, building further on these.
The only real mistake is the one from which we learn nothing.
Our testing principles
There's little meaning in setting a specific coverage-goal for automated tests. But, to give you an idea of "what is good enough", here's a few statements:
- Your test suite should be sufficient enough that a new developer can get comfort in knowing that their isolated change didn't break anything else in the infrastructure of the app.
- Your suite should make you comfortable that your app will behave as expected in production.
- Errors and bugs will always happen, but your suite should cover many of them, and expend as you find more.
- Your suite should help you identify bugs in production by excluding a number of test-covered scenarios.
Ground principles
Our apps are:
- Simple to run a test
- Create needed test-scripts and expose from your package.json
- Easily testable code
- When writing code, try to structure it in a way that it is easy to write tests for it.
- Break large functions into smaller parts, they are easier to test, and makes for cleaner code.
- Self-learning
- When fixing bugs, get the habit of adding tests for that particular case.
- Did the app crash if user sent in a malformed date? Add a test for it.
- Did it crash if a specific URL was entered too early? Add a test for it.
- There's tons of learning in your app's logs.
- Stand-alone
- If your app depends on anything critical to work, that you do not control, like external APIs, how will the app behave when these are down (or just very slow)?
Never allow the same bug to bite you twice.
Writing tests
Ideas, change requests, or comments?
We are always open for discussions, ideas and comments about our principles.
Tooling
The team selects their own tooling based on needs. Here are the most popular across Gjensidige (in bold), with alternatives that are popular world-wide. Share your experiences with these and other tools in #frontend.
- Using Vitest (or Jest, or bun:test) as test-runners.
- Using React Testing Library is popular.
- Using Playwright or Cypress for browser-based testing, like interacting with forms, and taking screenshots.
- Accessibility testing using pa11y is advised. It can help you roughly about 20% of accessibility issues.
Healthy patterns
- Meaningful tests
- Don't add tests just for the sake of having more tests
- Adding a slew of tests that test obvious things, that doesn't detect errors and bugs before going into productions, will not help you.
- The purpose of a test is to let the code find bugs for you - put your effort where it counts.
- Sane snapshot-testing
- Be aware of that snapshots can give false comfort, the appearance that you have many tests. But in reality many developers re-generate snapshots just to solve errors, leading to them not being stopped from making mistakes.
- Changing a little HTML and/or CSS can cause a lot of "noise" in git.
- Never test other products
- Like Builders Core, shared libraries, or 3rd party libraries, assume they work as intended.
- Test your own logic, code and components.
- Write tests using selectors for what you can see
- Like the text of a button, a class, element-name, role, or something else that is unique enough.
- Refrain from using data-testid, there should be other ways to select your element.
- But if there's no other way, of course use it.
- CI-ready
- All tests shall be able to run on CI (GitHub Actions).
- Dependencies you need for your testing suite (like jest, vitest, etc) are added as devDependencies.
- Mock APIs and services a user cannot be expected to have locally (see mocking).
On mocking
- We store mock data alongside our projects so they can be run locally without much hassle.
- Mock responses from dependencies in a way that you can run tests without other services being up, while still making sure your own app's logic works.
- Mock data should never contain sensitive or secret values (like passwords, SSN, etc.).
Principles for building web applications
See the guiding principles that help us increase the overall quality of our digital solutions.
Universal design through code
Developers have a particular responsibility for universal design. Here's what to consider, what to look for, and how to improve your apps accessibility through code.
Get started with Core
New to our design system? Whether you're a designer or developer, you'll find everything you need to know in our documentation in Storybook.