Nobody told me how fun TDD was…

You solve one problem… and you solve the next one… and then the next. And if you solve enough problems, you get to come home. -Mark Watney

Mark Watney, the fictional astronaut played by Matt Damon, was not talking about Test-driven Development (TDD) when he spoke these words at the end of The Martian — but they could not be more fitting. When is testing your web app not as dramatic as needing to survive an alien planet?

When I finished watching The Martian, I was also in the middle of familiarizing myself with TDD. I heard the above quote with wide eyes, it’s perfect! Replace “…you get to come home” with “…you get a web app” and it’s TDD in a nutshell.

You solve one problem, and you solve the next one, and then the next. And if you solve enough problems, you get a web app. -Me and Mark Watney

I had an embarrassing lack of experience when it came to testing code so I decided to just start doing it.

I built a simple Rails To-Do List app using a TDD methodology. I wrote Integration Tests for a feature (Unit Tests when needed), wrote code that passed those tests, and moved on to the next feature. After all the features of the app had tests and associated code, I had barely started the Rails server to see the app until it was complete and fully functional. I used Rspec and Capybara to write my tests.

feature 'User logs in and out' do
   describe 'log in process' do
    context 'from the home page' do
       it 'should click log in' do
visit('/')
click_on('Log in')
expect(page).to have_current_path(user_session_path)
end
  ...

Within the Rails app, I installed the following gems to make testing, and my life, easier:

  • rspec-rails: main testing framework.
  • capybara: simulates how a real user would interact with the app. Useful functions like click_button(‘Save’).
  • launchy: this is a real life saver. I mentioned above that I rarely booted up the rails server to manually test features throughout the development process. However, there are times you need to see why tests are failing. i.e. “I know there is a link on the page, why am I getting the error that no link is found?” Capybara has the useful function save_and_open_page for exactly this reason. It takes a snapshot of what it sees on the page and saves it. Launchy allows you to be that much more lazy and does all the work of opening that snapshot in your default browser automatically.
  • factory_girl_rails: one challenge I encountered while testing my app was the same user being created multiple times in the test DB. This would obviously throw an error every time I ran my tests: this user already exists. I installed the factory_girl gem as a way to combat this. It didn’t actually help me solve the issue but it did help me write less code.
  • database_cleaner: This helped me solve the issue! Database_cleaner, as the name suggests, ensures a clean test DB while running tests. No more: this user already exists!
  • devise: for user authentication.

Benefits

Testing code is a polarizing topic among developers. Some do a lot of testing, some test only if it’s absolutely necessary, while others don’t test at all. As a junior web developer, the benefits I experienced while testing my To-Do app were immense.

So often as a Master of None Developer (also see: Jr. Developer), it’s easy to lose focus on how to do something vs. getting something done. I have built CRUD Rails apps in the past, but I had never focused and learned so much until I did the same thing with TDD.

I wrote tests for a user adding, editing, and deleting a To Do List. I ran the tests and the first error I got was telling me I had no Lists controller. So what do I do? Add a Lists controller. I do this over and over again. The errors tell me there is no template for Lists, no edit or create action, etc. I solve the problem each error is concerning and then the next until the feature is fully fleshed out. Each step needed to complete a basic Rails CRUD app is ingrained through this process. I’m familiar with railsy errors, I better understand how Rails works, and I know my app inside and out.

The biggest surprise throughout this process though, was to find out that TDD was fun!

Building out my Rails app this way was more enjoyable through test-driven development. It gamified developing the app. Passing each test was a checkpoint urging you to push forward to the next feature.

There are obvious benefits to testing your code. Well-written, thought-out tests will protect your code from your future self or other contributors. But if that’s not enticing enough, try TDD because it’s fun. It’s a gamified approach to something you’re already doing. If you identify as a Master of None, TDD will also enable you to understand the framework you’re working with in greater detail.