Confident JS series: Part 3 — Test what improves your confidence
Be happier with your tests
This is part 3 of a series:
- Part 1 — Encoding and Decoding payloads for saner applications
- Part 2 — Types, JSDocs, and declaration files
- [You are here] Part 3 — Test what improves your confidence
- Part 4 — A bit more functional
- Part 5 — Task, Either and Boxes
- Part 6 — Fp-ts and io-ts, now it’s time to get serious
To write or not to write tests
Creating applications is a hard work, and sometimes the feeling is that we are dealing with something like this:
Anyone can build an application, but when we talk about building something with quality in mind with a well tested codebase then things start getting tricky
During my career as a Front-end developer, I can summarize two major fail case scenarios related to tests.
Over-testing
Sometimes we’re more concerned on improving the code coverage or writing as much tests as we can, and its hard to tell if that is actually improving our application’s quality.
I had a perception that we were supposed to test everything, I even wrote an article series on how to apply TDD in the Front-end.
In a previous company, my team developed a simple two page application in which consisted in just two requests, one to fetch, and the other post data to populate a dashboard.
We had over 400 tests… really 😅
The major mistakes I’ve made were:
Having the wrong abstraction
We are so conditioned in the JS world to break down things, and most times that is more or less like a “future prediction”, by trying to go too much ahead of time, we might compromise our application and test structure with premature decisions.
I highly recommend reading of the following contents to know a bit more on breaking a few habits of our ecosystem.
Shallow mounting
I can refactor my component’s implementation and my tests break.
I can break my application and my tests are passing.
Testing implementation details
A great way to get a lot of false negatives and false positives 😉
Those mistakes caused a lot of pain when we had to deal with things like component signature changes, making sure our tests were actually breaking when they should break, and specially, deal with API contract changes.
Soon after the first release, we’ve noticed most of our tests didn’t actually validated anything relevant, we could erase most of them and we would end up with the same level of confidence.
Testing neglect
This is probably the most common scenario I lived in my career, and when we never have time to invest in quality, our company pay’s the bill, either by:
- Losing clients trust due to bugs and problems that might happen
- Putting money into the problem either by investing on infrastructure or hire more developers, most times without the actual need of that (hello memory leaks)
- Time wasting on unneeded manual testing every time something change
- Unbearable tech debt that might result in “application re-writes”
- Getting sued because a vital part of your system didn’t worked in a crucial operation
Balance between quality and speed is crucial
Test what improves your confidence
Things started clicking when I first saw the Testing Library, and I began to read and watch Kent C. Dodds content.
The more your tests resemble the way your software is used, the more confidence they can give you.
When I read that sentence for the first time, front-end testing suddenly started to make more sense.
I used to apply by heart what I mentioned in my TDD series, and I still do a few of those concepts, but now, I try to look carefully on what really matters to be tested.
How?
Currently I like to use Testing Library to test my front-end applications since you:
- Can write tests that resemble more your application use
- Don’t have the freedom do to whatever you want, you can’t make things that might lead to a irrelevant/inconsistent test cases (e.g: change programming implementations, shallow mount components)
- Can use the same environment for multiple frameworks and environments
- Helps you improve your application accessibility
- It naturally helps you creates nicer tests for your components
This is not a “testing guide”, maybe in a future article 😉, but I want to compare a few things I’m doing differently since my TDD series, below you can see a comparison on the approaches.
Just a brief overview of the project:
It’s a Github user search app, you can search someone by its username and then we print the result in the screen.
❗️Since this is a comparison with my TDD series, we are not handling loading state, error scenarios and alternative paths on purpose to keep it simple, we will implement a few things we already saw in previous parts, and I will show in the next parts on how to deal with those scenarios we are not covering here❗️
You can find the old part here on the main
branch:
And if you want to compare, you can check the new implementation here on the testing-library
branch:
It’s not the prettiest refactor, nor the way I actually “do” things on my daily basis, but it is a naive approach on what we talked until now.
The older version we have around 12 tests, and in the newer version we have only 1 test that gives us enough confidence in the main purpose of the application
How a test like that would “replace” the 12 from the previous version?
Well, most of those 12 tests, we are trying to test more individual pieces of our application, and with this other test we are automatically covering all desired parts of the scenario.
A few key points on that test:
- It is way shorter
- It tests the working application for a specific scenario
- In this case, we don’t want to define a strict implementation contract, we just want to guarantee that the expected behavior works
- The only layer that is mocked is by using Mirage.js that goes beyond the scope of the application, this means that we are not mocking any application behavior
- The only thing we can’t guarantee here is in cases where the API response is different from what we defined in Mirage (but we could create an e2e test to validate that), either way we have our decoders in place to guarantee runtime consistency
- The E2E test would be very similar to this code
Why not just create a E2E test then?
Well… E2E tests are slow, in some cases it requires a mature testing environment since you will probably need a special staging environment just to run your tests.
E2E will give you that final degree of confidence, but probably you won’t be happy to wait the suite to run every time you change your code.
With this integration test we gain a high degree of confidence, the test runs quickly and you will also end up with a mock server, which can be used in development environment to manually test other scenarios or just as a “dummy server” for your application.
My learned lessons
It is up to us, developers, to push testing culture, we can’t expect the product quality to increase itself, we have the responsibility with ourselves, our clients and our company to ship the best possible solution
- It’s OK to not invest in tests right away, but this must be an aware decision with a future plan on when that will happen
- Testing in the front-end can be hard, so don’t worry on making mistakes or not knowing how/what to test, experience comes with time, just keep studying and applying anything you’ve learn… caring about quality its the first step
- Revisit your tests and refactor them, they are also part of the codebase that might need maintenance
- Gain confidence by testing relevant parts your application before thinking in a refactor
- If your environment doesn’t encourages quality culture and you can’t change that, maybe this is not the right environment for you
Conclusion
Nowadays there are so much content on front-end testing subject that there is no excuse to not apply that in your daily work, in serious personal projects, or even in company code challenges.
Here you can see a few courses and books regarding this subject:
Thank you for reading this article. Please stay tuned to the next parts.
Do you like what you see?
Give us a clap, leave a comment, or share anywhere. We appreciate your feedback.
Also, check out other articles on our blog. We deal with many interesting things:
- 404: We have a problem
- How we achieved an automated color palette that designers and developers love
- Why and how we are doing E2E Tests
- VueJS components
- No-bullshit illustrations
- VueJS Component Library: Why we created our UI component library
- Testing vue-testing-library
- and more 😊!
Check out our openings at our dev team!
Sorry for the long post, here is a cat dressed as a cat.