Since I started working on the Ruby on Rails testing book, I've come across a lot of articles that really try to convince the reader why they should be writing tests for their Rails applications. They all seem to hit the same checklist of the benefits of testing (which there are plenty). What I haven't seen is anyone try to answer the question of why there are so many of us out there that knew the benefits of testing, but still weren't actively testing our Rails apps.
The following is a section taken from ‘What do I test?', my upcoming book on testing your Ruby on Rails applications. If you have been struggling to add testing to your workflow, you should buy the book early now and get $5 off the sale price.
We try to learn testing when we learn Rails
I don't know about you, but I'm relatively new to this whole "Web Development" racket. Whenever I'm learning a concept about programming or design, it's usually for the first time. A lot of Rails developers are self taught and rely on the "internet" to learn them some new skills. Doing a quick search will reveal a waterfall of Rails tutorials, books, videos and blog posts. This is why we love using Rails, because of the community. There is one consistent problem with these first-time learning materials, though. They encourage you to learn testing at the same time as you are learning the core concepts of Rails and maybe even web development in general.
Trying to work your way through these books and tutorials, it becomes apparent pretty quickly that writing tests will not make learning Rails any easier. Anything you can do to get your first application out the door faster is welcome, so it makes sense to skim over learning testing and focus on the basics.
This book is proof that trying to learn how to write tests at the same time as Rails just doesn't work. I fell off the horse, and I bet you did too. There's nothing wrong with that, as long as we try to get back on the horse.
Actually, don't get back on the horse. Get back to your computer. Horses make terrible workstations.
Writing tests takes longer at first
Do you know what really sucks? Putting in more time to a project than you need to. As a contract worker, I loathe when a project requires more time and attention than I thought. It messes up my entire schedule and just generally makes me cranky, and no one likes a cranky developer.
When I first started looking into testing, the idea of adding extra time to write tests before I even begin working seemed absurd. As far as my clients were concerned, they weren't getting any extra immediate value. So what if their application was well tested? They only cared about their features, and it was my job as both a developer and business owner to meet their expectations in the shortest amount of time possible.
Whenever I finally buckled down and started writing tests for client projects, I was irritated. It took extra time to figure out what the features were going to look like before I built them. I had to spend extra time learning the syntax and writing a few bad tests before I knew what I was doing. Worst of all, I didn't have anything to show once I finally had the tests written. The feature didn't even exist and I had already burned through a decent amount of time just fumbling around through tests.
Then, I built the feature in no time at all.
Then I built another feature with tests faster than the first time.
It was all starting to make sense. I wasn't taking longer to write these tests. I was just doing the hard part first. After I learned the assertion syntax for writing tests, I was working either as fast or even faster than I was before. While it's true that it takes a little bit of time to change your workflow to accommodate tests, once you get over that hump, you will get all that time back and then some.
Testing is not neccessary to build a Rails app
You don't have to write tests to be a Rails developer.
That's the hard truth that comes along with testing. It's not necessary to have a fully functional Rails application. You definitely need to understand how models, controllers, and views are represented in Rails. You can't get around an application without routes. And you won't be able to make changes to your models without migrations. There are plenty of things in the Rails world that are required. Testing isn't one of them. Once you understand that, it's very easy to prioritize your time and attention to other things that will affect the actual application directly.
Of course, this changes over time. Anyone who has added testing to their development workflow insist that an application doesn't work until it's fully tested. As we learn how to write tests, we'll find that tests might not be necessary for a working application, but damn do they help.
The community is split between Specs and Assertions
One of the big reasons to build your web apps with Ruby and Rails is because of the community behind them. The Rails community is highly opinionated, but generally agreeable on most subjects. If you are having a problem figuring something out, in all likelihood, you'll be able to find someone else who has encountered the same problem that can help you out. At the very least, you'll be able to find someone to tell you why you're having the problem. The Rails community is incredibly helpful.
That is, it's incredibly helpful until it comes to testing frameworks. Once you venture into this territory, you are presented with a very real problem. A large set of highly vocal, and highly skilled Rails developers regularly test their apps with the Rspec testing framework and syntax. Unfortunately, this set of Rails developers does not include the Rails core team. They, instead, use assertions found in the Minitest, which are bundled into Ruby and the Rails test objects. This means that, by default a large part of the community is directly in opposition to a Rails default which goes against the "convention over configuration" mantra.
With the community pulling you in two different ways, you can't help but feel like you might be doing something wrong. It also means that the chances of being able to troubleshoot any problems you may have gets cut to a fraction of what you could find if the community agreed.
When I was first picking up Rails, I was nudged towards using Rspec. While this isn't necessarily a bad thing, it was a confusing thing. The official Rails guides were pulling me one way, while community guides were pulling another. I ended up just throwing testing out the window because I felt like I was perpetually doing something wrong.
One of my strategies for getting Rails testing to stick was to think of it as just that: Rails testing. I try to do as much as I can the Rails way; testing should be no different. I've accepted that there are plenty of benefits to using another testing framework, but I won't get any of those benefits if I don't know how to test yet. Since I accepted that I was going to stick with assertions, things have gone much more smoothly.
Stick with the Rails default until you have a reason to change.
We often work alone
If you're a solo contractor like me, you've likely been the only developer responsible for a project. You know the ins and outs of the application and debugging is just a matter of remembering how you implemented a certain feature. We don't need to concern ourselves with other developers messing with our beautiful code. We are enlightened.
Of course, that's a lie. You're either never going to be the only developer on the project, or you will never be able to remember everything you've contributed to a project. Future you is an entirely different developer than present you. Tests make future you's life much much easier by self-documenting and validating your work as you go. Tests become a time capsule to make working with past you as easy as working with present you.
Another thing to take into consideration is you might not always be working alone. There may come a contract or a job where you would be working on a team. Teams love tests because they are a great way to reveal how an individual's code works. Writing tests on a team is your way of saying "My code works. See? Whatever you do, make sure this code still works." Being a good teammate means making sure you make it as easy as possible for your other team members.
Our development process isn't perfect
We aren't a bunch of math nerds with pocket protectors and calculators and protractors. We are Rails developers. We are creative problem solvers writing beautiful code. Do painters need a step-by-step plan to make their beautiful art? NO! Then why do I, as a fellow creative, need a process to help me write my beautiful code? I'm an artist.
At least that's what I tell myself, until I have to go into my alleged beautiful code and fix a feature that I didn't fully plan out, or when I have to debug a situation that I hadn't thought of until it happened. After hitting my head and cursing at the creative in myself for the twentieth time, I decided that it would be helpful to put more time and attention into having a cleaner, more intentional development process.
A good development process is one that makes me think before I start writing any lines of code. It's one that forces me to consider all the different situations that could exist, and build the feature to accommodate these situations. Most importantly, a good development process is one that only makes me think about these things once, and then lets me free my mind to creatively solve the problem. We're going to incorporate all of these into our workflow by mixing in some tests.
We work in spikes as we're learning
During the earlier part of my Rails career, It was no surprise to often find myself building something completely new. Maybe it was a feature that I hadn't had a chance to think about before, or maybe it was an entire type of application that I would have to fully research before starting to build. Either way, there were a lot of things I built early on that I approached with zero experience. This usually meant that I was working in a spike the whole time.
In the test-driven development world, a spike is a period of time that you are supposed to dedicate to building exploratory code. It's a time where you can figure out what you are going to build without having to worry about writing tests to support our work. Sound familiar? Then you probably have been working in very large spikes this whole time.
One of the first "aha" moments I had when taking a second crack at testing was understanding that I didn't know what I was about to build a lot of the time. So, I ended up spending a lot of time figuring out what I was building and how to build that. This is great, and impossible to avoid as a new Rails developer. A lot of things are going to be new, and you aren't going to know the end result yet.
One of the things we are going to do in this book is embrace the spikes that we have been working in, but turn them into good habits instead of bad. No longer will we be putting untested, "Hey it finally works" code into production.
We're in this together
These are all reasons that I wasn't writing tests. I started writing the book so I could understand what was holding me back from testing and actually start writing tests. I've made an active effort to keep track of those "aha" moments I had over the course of the last year, and worked to condense them into this one book about Rails testing. If you are the kind of Rails developer who wants to learn testing, but has had trouble adding it into your workflow, What do I test? is the book to help you do it.