Continuous Testing
with Ruby, Rails, and JavaScript
by Ben Rady, Rod Coffin
Version: P1.0 (June 2011)
Copyright 2011 Pragmatic Programmers, LLC. This book is licensed tothe individual who purchased it. We don't copy-protect itbecause that would limit your ability to use it for yourown purposes. Please don't break this trust-don't allow othersto use your copy of the book. Thanks.
- Dave & Andy.
Table of Contents
Copyright 2011, The Pragmatic Bookshelf.
Acknowledgments
We would like to thank everyone who offered encouragement and advice along the way, including our reviewers: Paul Holser, Noel Rappin, Bill Caputo, Fred Daoud, Craig Riecke, Slobodan (Dan) Djurdjevic, Ryan Davis, Tong Wang, and Jeff Sacks. Thanks to everyone at Improving Enterprises and the development team at Semantra for contributing to our research and helping us test our ideas. Wed like to thank Dave Thomas and Andy Hunt for giving us the opportunity to realize our vision for this book. Thanks also to our editor, Jackie Carter, for slogging alongside us week by week to help make that vision a reality.
Wed also like to thank all the Beta readers who offered feedback, including Alex Smith, Dennis Schoenmakers, Johnneylee Jack Rollins, Joe Fiorini, Katrina Owen, Masanori Kado, Michelle Pace, Olivier Amblet, Steve Nicholson, and Toby Joiner.
From Ben
I would like to thank my wife, Jenny, for supporting all of my crazy endeavors over the last few years, including this book. Theyve brought us joy and pain, but youve been by my side through it all. Id also like to thank my mom, who first taught me the value of the written word and inspired me to use it to express myself.
From Rod
I would like to thank my wife for her encouragement and many sacrifices, my brother for his friendship, my mom for her unconditional love, and my dad for showing me how to be a husband, father, and citizen.
Copyright 2011, The Pragmatic Bookshelf.
Preface
As professional programmers, few things instill more despair in us than discovering a horrible production bug in something that worked perfectly fine last week. The only thing worse is when our customers discover it and inform usangrily. Automated testing, and particularly test driven development, were the first steps that we took to try to eliminate this problem. Over the last ten years, these practices have served us well and helped us in our fight against defects. Theyve also opened the doors to a number of other techniques, some of which may be even more valuable. Practices such as evolutionary design and refactoring have helped us deliver more valuable software faster and with higher quality.
Despite the improvements, automated testing was not (and is not) a silver bullet. In many ways, it didnt eliminate the problems we were trying to exterminate but simply moved them somewhere else. We found most of our errors occurring while running regression or acceptance tests in QA environments or during lengthy continuous integration builds. While these failures were better than finding production bugs, they were still frustrating because they meant we had wasted our time creating something that demonstrably did not work correctly.
We quickly realized that the problem in both cases was the timeliness of the feedback we were getting. Bugs that happen in production can occur weeks (or months or years!) after the bug is introduced, when the reason for the change is just a faint memory. The programmer who caused it may no longer even be on the project. Failing tests that ran on a build server or in a QA environment told us about our mistakes long after wed lost the problem context and the ability to quickly fix them. Even the time between writing a test and running it as part of a local build was enough for us to lose context and make fixing bugs harder. Only by shrinking the gap between the creation of a bug and its resolution could we preserve this context and turn fixing a bug into something that is quick and easy.
While looking for ways to shrink those feedback gaps, we discovered continuous testing and started applying it in our work. The results were compelling. Continuous testing has helped us to eliminate defects sooner and given us the confidence to deliver software at a faster rate. We wrote this book to share these results with everyone else who has felt that pain. If youve ever felt fear in your heart while releasing new software into production, disappointment while reading the email that informs you of yet another failing acceptance test, or the joy that comes from writing software and having it work perfectly the first time , this book is for you.
Using continuous testing, we can immediately detect problems in codebefore its too late and before problems spread. It isnt magic but a clever combination of tests, tools, and techniques that tells us right away when theres a problem, not minutes, hours, or days from now but right now, when its easiest to fix. This means we spend more of our time writing valuable software and less time slogging through code line by line and second-guessing our decisions.
2.1 Exploring the Chapters
This book is divided into two parts. The first part covers working in a pure Ruby environment, while the second discusses the application of continuous testing in a Rails environment. A good portion of the second part is devoted to continuous testing with JavaScript, a topic we believe deserves particular attention.
In Chapter 1, , we give you a bit of context. This chapter is particularly beneficial for those who dont have much experience writing automated tests. It also establishes some terminology well use throughout the book.
The next three chapters, Chapter 3, , show how to create, enhance, and use a continuous testing environment for a typical Ruby project. Well discuss the qualities of an effective suite of tests and show how continuous testing helps increase the quality of our tests. Well take a close look at a continuous test runner, Autotest, and see how it can be extended to provide additional behavior that is specific to our project and its needs. Finally, well discuss some of the more advanced techniques that continuous testing allows, including inline assertions and comparison of parallel execution paths.
In the second part of the book, we create a CT environment for a Rails app. In addition to addressing some of the unique problems that Rails brings into the picture, we also take a look at another continuous test runner, Watchr. As well see, Watchr isnt so much a CT runner but a tool for easily creating feedback loops in our project. Well use Watchr to create a CT environment for JavaScript, which will allow us to write tests for our Rails views that run very quickly and without a browser.
At the very end, weve also included a little bonus chapter: an appendix on using JavaScript like a functional programming language. If your use of JavaScript has been limited to simple HTML manipulations and youve never had the opportunity to use it for more substantial programming, you might find this chapter very enlightening.
For the most part, we suggest that you read this book sequentially. If youre very familiar with automated testing and TDD, you can probably skim through the first chapter, but most of the ideas in this book build on each other. In particular, even if youre familiar with Autotest, pay attention to the sections in Chapter 2, that discuss FIRE and the qualities of good test suites. These ideas will be essential as you read the later chapters.