Delete your development database

Do you TDD?

It is my experience that most developers generally agree with Test Driven Development, but a lot have trouble actually putting it into practice. Such excuses include "but I work on a legacy app", "I don't know what I'm going to build", or "DHH said TDD is dead". I love TDD, but I have also found myself running into trouble adhering to general TDD principles and reaching for excuses.

I recently rejoined the company I work for after leaving for a year. The production database is a little over 100GB and the app is so data driven that it is just assumed that everyone has production data on their machine for development. As you could imagine, a 100GB takes a long time to download, and I just never got around to doing it. I already knew the app because I had worked on it for years before leaving. This put me in a unique place; I don't need to poke around the application in development to understand it as you would normally do when starting a new gig and setting up your machine for development.

The first ticket I worked was a fairly involved feature and I decided I would try to follow a strict TDD process. Since I didn't have a development database I couldn't make a code change and check the app quick to see if it worked. I had to write tests in order to verify the changes I was making worked. Overall I would say I had a great experience and I'd like to share what I feel worked and didn't.

Good, fast, cheap. Pick 2

One thing I've only heard a few folks mention when talking about why they don't use TDD is that it makes development take longer. I feel like many more people think this than actually say it, I myself have thought it a different points in my career. Can we write more code faster if we do not require a failing test before any code change? Sure, why not.

Let's talk about what it means to fast. If you ship a broken feature and have to fix it later, is that faster than shipping a working feature? If QA returns your ticket because it doesn't work, is that faster? Of course not. Obviously, even with TDD we can still make these same mistakes, but in my experience they are far less common. During development I was using Capybara for integration tests to test the front end logic I was adding. By nature, these tests take longer to run than unit tests because they are clicking the browser. You can save screenshots and even access console.log statements, however you still have the overhead of running the integration test each time. At some point you need to get stuff done, and this was when I strayed from my strict TDD process.

My point here is that there comes a time where we have to deliver. I do not feel that saying "sorry boss, we couldn't ship the feature because we couldn't debug the front end in a timely manner." is something professional software engineers should do. We need to consider practicality when developing software and blindly adhering to any process without give may lead to problems. When I was writing this feature I was not very familiar with JavaScript unit tests which would have definitely helped me move faster here. There is also some overhead to adding something like Jasmine to your test suite. If you're behind schedule it might not be the best time to add and learn something like Jasmine instead of adding a few console.log statements to get moving. I 100% advocate unit testing all JavaScript, but we have to be realistic. If you've never unit tested JavaScript before there is going to be some effort into understanding how to write them.

We could make the same assertions as above about being cheap. If you ship a broken feature and have to fix it later, is that cheaper than shipping a working feature? If QA returns your ticket because it doesn't work, is that cheaper? Of course not. So can TDD reduce cost of software development? When we were talking about speed, I wasn't already prepared to test JavaScript at the unit level. With Capybara I'm still able to write failing tests before writing production JavaScript code, but there is a much slower feedback loop. The cost of preparing for JavaScript unit tests up front, should be less than realizing the time they could save after the fact. With greenfield apps the time to run Capybara style integration tests could be relatively fast. We might not realize the amount of time we could save with unit level JavaScript. We can make the correlation to money when we with about the amount of time saved as a team in this regard. If every developer is spending an extra 5,10,30 seconds per test run the amount of money spent on development goes up exponentially by the number of developers.

The idea of good software is subjective. When the software is for your car's transmission, good means something very different than your average CRUD web application. Thankfully we aren't talking about embedded systems here, but in my opinion the same standards apply. We must demand professionalism in our industry and shipping software that does not work(not good software) is unacceptable. As software engineers we understand the effect of quality, maybe even more than our users. It is easy to draw the conclusion that every line of production code is driven by a failing test leads to good software. However this does not account for side effects created by adding more functionality/complexity. During development I was testing my Ruby code at the unit level and JavaScript at the integration level through browser tests with capybara. Since integration tests are slow I did not cover all the possible paths, as you would with unit tests, through the JavaScript code. This caused me to not notice a side effect introduced by the feature I implemented. All my code was driven by a failing test, however this did not lead to a feature with out any defects.

Overall I feel that TDD leads us to cheaper and faster(in terms of development time) code. Which is interesting because that is mostly the opposite of the sentiment of folks who oppose TDD. One reoccurring theme here was the lack of unit test for my JavaScript. Without proper unit test coverage through all paths of your code, defects will occur. I was still following the TDD mantra of "red, green, refactor", but writing tests at the integration level caused me to miss side effects introduced by the new feature. I feel that the cost of setting up your tools up front is far less than realizing you need them later into a project. I'm not sure if you should actually delete your development database and have no other way to interact with your code other than tests. If you are familiar enough with the application you're working on, it is definitely worth the experience. For me a good compromise was a development database without production data, and this is my current setup.