Thomas McGoey-Smith

Getting Started with TDD using Ruby & Minitest

I have to confess! I’m what you would call a code slinger - code cowboy, someone who doesn’t test their rails code!

Things were going good until I had someone manually test my code (it wasn’t pretty!).

perfect code

How do you even TDD?

First off, what is TDD (or Test Driven Development).

“First the developer writes an (initially failing) automated test case that defines a desired improvement or new function, then produces the minimum amount of code to pass that test, and finally refactors the new code to acceptable standards.” — Wiki

In other words.

Write test code that fails, implement just enough of your method until the test passes. Then clean things up.

Let’s try some TDD with MiniTest

Make sure you’ve installed Minitest. I’m using Minitest 5.6.1 & Ruby 2.2.2.

I’ve been working on Trolley, a simple tool that lets Gumroad creators accept PayPal.

I wanted to save part of the short_url - i.e. extract trGXA from https://gum.co/trGXA.

Let’s first stub out the class where this method lives.

class Gummy
  def parse_short_id (short_url)
    # Magic Goes here...
  end
end

Now let’s setup our test.

require 'minitest/autorun'
require 'minitest/pride'
require './gummy'

class GummyTest < Minitest::Test

  def setup
    @gummy = Gummy.new
  end

  def test_parse_short_id
    assert_equal "trGXA", @gummy.parse_short_id("https://gum.co/trGXA"), "test parse short link id"
  end

end

Now run your test: $ ruby gummy_test.rb.

You should end up with something like this:

tdd test failing!

Now we want to write as little code we can to get our test to pass.

class Gummy
  def parse_short_id (short_url)
    short_url.sub(/^https?\:\/\/gum.co\//, '')
  end
end

tdd test passed!

Are we done?

Well, if we only ever expected our short urls to always be: https://gum.co/RaNdomId, then sure. But what happens if we passed the wrong URL, or we forgot the s in the https?

Our code wouldn’t be much use.

Let’s try it out in irb (this is where our cowboy skills shine!).

$ irb
'http://thomas.codes/trGXA'.sub(/^https?\:\/\/gum.co\//, '')

It gives us this:

=> "http://thomas.codes/trGXA"

That’s not very helpful. Let’s say our goal is to either return a valid extracted ID, or just nil for everything else.

Let’s add a new test case to cover what we saw in irb.

require 'minitest/autorun'
require 'minitest/pride'
require './gummy'

class GummyTest < Minitest::Test

  def setup
    @gummy = Gummy.new
  end

  def test_parse_short_id
    assert_equal "trGXA", @gummy.parse_short_id("https://gum.co/trGXA"),
                 "test short link id"
  end

  def test_parse_incorrect_short_id
    assert_nil @gummy.parse_short_id("http://thomas.codes/trGXA"), "test incorrect short id"
  end

end

tdd test passed!

Now we’re getting somewhere! Here’s a new version of our parse short id method:

class Gummy
  def parse_short_id (short_url)
    short_url.include?("https://gum.co/") ? short_url.sub(/^https?\:\/\/gum.co\//, '') : nil
  end
end

tdd done (for now)!

TDD is great when you have a grip on your design!

TDD is pretty slick when you know what your needing to design, but sometimes you just need to hack on irb and figure things out before writing that test.

Till next time.

@tamcgoey on May 05, 2015

Enjoyed the article? Subscribe to my newsletter for more.

© Thomas McGoey-Smith (2014-2018). RSS.