Preface
This is a book about dogma. My dogma. It is a set of principles, practices, and rituals that I have found to be extremely beneficial when building React applications. I try to apply these ideas in my daily work, and I believe in them so much that I take every opportunity to teach others about them. That’s why I’ve written this book: to show you the ideas that have helped me be successful in my own career.
As with any dogma, you are free to make your own mind up about it. There are people who will dislike everything about this book. There are those who will love everything about this book. Yet more people will absorb some things and forget others. All of these are fine. The only thing I ask is that you maintain an open mind while you follow along and prepare to have your own dogmas challenged.
Test-driven development (TDD) did not originate in the JavaScript community. However, it is perfectly possible to test-drive JavaScript code. And although TDD is not common in the React community, there’s no reason why it shouldn’t be. In fact, React as a user interface platform is a good fit for TDD because of its elegant model of functional components and state.
So, what is TDD, and why should you use it? TDD is a process for writing software that involves writing tests, or specifications, before writing any code. Its practitioners follow it because they believe that it helps them build and design higher-quality software with longer lifespans, at a lower cost. They believe it offers a mechanism for communicating about design and specification that also doubles up as a rock-solid regression suite. There isn’t much empirical data available that proves any of that to be true, so the best you can do is try it out yourself and make your own mind up.
Perhaps most importantly for me, I find that TDD removes the fear of making changes to my software and makes my working days much less stressful than they used to be. I don’t worry about introducing bugs or regressions into my work because the tests protect me from that.
TDD is often taught with toy examples: to-do lists, temperature converters, tic-tac-toe, and so on. This book teaches two real-world applications. Often, the tests get hairy. We will hit many challenging scenarios and come up with solutions for all of them. There are over 500 tests contained in this book, and each one will teach you something.
Before we begin, a few words of advice.
This is a book about first principles. I believe that learning TDD is about understanding the process in exceptional detail. For that reason, we will not use React Testing Library. Instead, we will build our own test helpers. I am not suggesting that you should avoid these tools in your daily work – I use them myself – but I am suggesting that going without them while you learn is a worthwhile adventure. The benefit of doing so is a deeper understanding and awareness of what those testing libraries are doing for you.
The JavaScript and React landscape changes at such a pace that I can’t claim that this book will remain current for very long. That is another reason why I use a first-principles approach. My hope is that when things do change, you’ll still be able to use this book and apply what you’ve learned to those new scenarios.
Another theme in this book is systematic refactoring, which can come across as rather laborious but is a cornerstone of TDD and other good design practices. I have provided many examples of that within these pages, but for brevity, I sometimes jump straight to a final, refactored solution. For example, I sometimes choose to extract methods before they are written, whereas, in the real world, I would usually write methods inline and only extract when the containing method (or test) becomes too long.
Yet another theme is that of cheating, which you won’t find mentioned in many TDD books. It’s an acknowledgment that the TDD workflow is a scaffold around which you can build your own rules. Once you’ve learned and practiced the strict version of TDD for a while, you can learn what cheats you can use to cut corners. What tests won’t provide much value in the long run? How can you speed up repetitive tests? So, a cheat is almost like saying you cut a corner in a way that wouldn’t be obvious to an observer if they came to look at your code tomorrow. Maybe, for example, you implement three tests at once, rather than one at a time.
In this second edition of the book, I have doubled down on teaching TDD over React features. Beyond updating the code samples to work with React 18, there are few usages of new React features. Instead, the tests have been vastly improved; they are simpler, smaller, and utilize custom Jest matchers (which are themselves test-driven). Readers of the first edition will notice that I’ve changed my approach to component mocks; this edition relies on module mocks via the jest.mock
function. The book no longer teaches shallow rendering. There are other smaller changes too, such as the avoidance of the ReactTestUtils.Simulate
module. Chapter organization has been improved too, with some of the earlier chapters split up and streamlined. I hope you’ll agree that this edition is leaps and bounds better than the first.