“But, wait. So you don’t write unit tests?”
Recently I’ve been asked how I approach the unit vs. integration vs. e2e debate. I’ve answered it twice below
NOTE: This post was first published in my newsletter. Subscribe to receive my posts a week earlier, right to your inbox 🚀
I don’t really care about names.
Write tests that provide a higher degree of confidence in your application.
Write a test before writing the “production” code that should make it pass.
Make sure your test suite is fast and cheap to run and maintain.
When I code a new feature, I like to start writing an application-level test using Cypress and Cypress Testing Library. This test is gonna stay in red until the whole feature is developed. Or, at least, the happy path I was focused on.
But having a single application-level test feels too detached from the code I write. It’s not enough, as I want faster and fine-grained feedback.
TDD doesn’t mean skipping design, though. I try to observe and understand the feature. Then I try to find the right spot to start coding it, making small changes driven by my tests. I keep on coding until Cypress tells me I’m done.
However, TDD is not always possible. Sometimes I need to step out of its cycle — mostly because I suck at it. In those cases, I make sure critical components and their edge cases are tested no matter what.
Don’t skip testing this
You might use TDD, you might not. However, I can think of three scenarios where testing should always happen:
- What are the most critical parts of your app from a business perspective? Test them.
- What files change more often? Use git to answer this question. And then test them.
- What files are introducing a higher number of bugs? Test them (and write the test before fixing the bug!).
It might not work for you
My approach might not work for you. However, some of its principles could be useful regardless:
- Start with a failing test.
- Do not refactor your code until the test is passing. As a wiser man once said, “Make it work, make it right, make it fast”.
- Alternate between bird’s eye view and down-to-metal testing. App-level tests cover more lines of code at once, while component-level and function-level tests provide faster and more focused feedback. Combine them.
- When not using TDD, focus on business value and bugs density to decide what to test.