My top 5 learnings on test driven frontend development
I spent 100+ hours in the past few weeks on TDD for frontend and want to share my top five key insights with this post.
1. Unit is not certainly a method
unit in Unit testing is often referred to as the smallest piece of software. That's simply not true. A unit shall rather be interpreted as an encapsulated module, with a few entry points in its public API.
Note in real-world scenarios, multiple classes still exist. They are however often exposed via a Facade. This makes interacting with the API much easier.
Thinking further, this answers the question of `how to test private methods?`. You simply don't test them. They shall be tested via the public API implicitly.
2. Test behavior, not implementation
Seeing, that a majority of TDD beginners try to test every method of a class, Daniel Terhorst North embossed a new term: BDD. Behavior-driven development.
It's not the test anymore, that gets the spotlight. It's the behavior.
Codebases change. Classes disappear. Private methods change their signatures. Behavior stays the same.
Internalizing this, you will soon build much more robust tests. Even after a gigantic refactoring, they should still pass.
Whereas testing implementation (testing each method of each class) will leave you with multiple broken tests, once any class changes its structure.
3. Writing tests first will have the greatest benefit
There are multiple reasons why you should always write tests before production code:
Let's be real here: You just won't write the test afterward. It works. Why would you need a test anyway?
You will experience the DX of your module. Hence you will think about a better design for it. Writing it afterward will leave you with your bad first DX draft.
You will see the boundaries of your computer. HTTP Clients should be abstracted since they cross the boundaries of your system.
Do yourself a favor and code test-driven. Not code-driven with tests.
4. Keep your views dumb
You don't want your view to contain any business logic. Their only responsibility is to display values and delegate user events.
As a practical example, let's take a drag-and-drop feature in Angular. You could either:
Put all drag-and-drop logic into a component
Abstract user events (eg.
dragStart, ...) and handle the logic in a plain old typescript class
Using the first approach won't be reusable and very hard to instantiate. The second approach would give us the freedom, to write tests without even thinking about a DOM.
Furthermore, views and styling behave just like our previously mentioned
HTTP clients. They cross the boundaries of our computer system and you don't know the output.
Pro tip: If you want to visually test the UI there are great tools like Storybook. Even without any testing framework, the process of red, green, refactor remains.
5. TDD is a skill that takes time to practice
My Karate teacher always says: if you have questions about a Kata, repeat it ten-thousand times. Your questions will vanish.
TDD is the same. It's something that you need to practice many times. Over and over again.
It isn't something learned within one day, week, or month. You and your team will have to invest time to learn the fundamentals. Become better and perfect the skill.
Please don't be one of these tech leads saying: "We don't follow TDD. It just didn't work out within a month". That's nothing more than Jesus Driven Development.
Hopefully, this could help you with some of your questions about TDD in front-end development and give you the motivation to start.
Feel free to share it with your colleagues to write better code as a team.