I am pleased to see testing taking a bigger hold in software development circles over the past few years. It is especially pleasing to see that TDD and BDD are really catching on as the best way to ensure that it’s done well. I’ve seen a lot of projects over the past few years, and the number that I see without an attempt at a comprehensive test suite is smaller every year. It warms my heart.
I often get introduced to a project with a very proud exclamation: “Not only do we have tests for everything, they were written first!” I’m sure most of you will understand that there’s not a lot related to testing Ruby that I’m likely to find new and exciting. Sometimes there’s a neat hack, or an interesting idea, but it’s inevitably variations on a theme I’ve been intimately involved with for the past 5 years. It’s not just because of my involvement, though, it’s because testing Ruby is the easy.
I don’t get excited when a team tells me they test drove their Rails application. I expect it. It’s part of Doing Your Damned Job. Testing Rails applications is a solved problem.
I often get excited by their enthusiastic proclamation of testing, though, and I ask hopefully “What are you using to test the JavaScript?”
“Oh, uh, well, you see, uh, we only tested the Ruby parts. Testing JavaScript is hard!”
My heart sinks every time. There’s a simple reason why, and I’m going to embolden it for you, because it’s important. If browsers still had a blink tag, the following would be an appropriate usage:
The stuff that’s hard to test is the stuff that needs it the most.
This isn’t just related to writing JavaScript in a web application. This is a universal truth. A very common reason why things are hard to test is that they’re tightly coupled and have really mucky dependencies1. If something is tightly coupled and has really mucky dependencies, your tests will shine a floodlight on them and provide you with a roadmap for cleaning them up.
When you test the Ruby parts of your Rails project, that’s great. I’m glad you’re making an effort to Do Your Damned Job. But if you rely on JavaScript (or other languages, for that matter) those parts need to be treated with the same care and attention that you paid to the Ruby parts. Testing part of your application is not Doing Your Damned Job.
Part of the problem with testing JavaScript is one of bootstrapping. Getting the testing frameworks set up and running can be combersome. Many of them are poorly documented, lots are incomplete, and some just aren’t that great. Why do you think that is? Because only a small fraction of the people are doing their damned jobs and building comprehensive software all the way down. Pick a framework, use it, and write about your experiences.
Consider a Rails application that has a beautiful test suite for all of the Ruby stuff and none for the JavaScript. You’ve tested the parts that interact with the database, the basic workflow, and the backend of the application. The stuff you left out is the stuff the user sees and interacts with heavily. Because of the tight coupling and dependencies, the stuff you haven’t tested is the most fragile.
Question: Is it most likely to break in front of the user because it’s JavaScript and JavaScript testing is hard, or is it most likely to break because you didn’t test it?
Answer: Your users don’t care.
If testing is part of Doing Your Damned Job (hint: it is) then it certainly includes testing the hard part.
So if you send me a Rails project that has nice comprehensive tests for the Ruby, and a hairy unmaintainable mess of JavaScript, don’t be surprised if I say “Hey, thanks for doing the easy part.”2
Watch this space for some notes from the trenches on testing the hard stuff.
1. This is especially true of JavaScript: it’s tightly coupled to the browser and the DOM, and the dependencies on both are mucky.
2. I probably won’t mutter “fucker” under my breath, but don’t be surprised at that, either.