Andre
Andre

Reputation: 29

Test Driven Development with Ruby

I'm new to testing and need a little help getting started with TDD. I have a simple app that takes some txt files and reformats them for different outputs.

Here is an example of the txt file

Smith | Steve | D | M | Red | 3-3-1985
Bonk | Radek | S | M | Green | 6-3-1978
Bouillon | Francis | G | M | Blue | 6-3-1975 

And here are my methods to change the outputs of this text file in an app.rb

def pipe
 alpha = File.readlines('pipe.txt').sort 
 alpha.each {|line| line.gsub! '-', '/'}
 alpha.each {|line| line.gsub! '|', ''}
 alpha.each {|line| line.gsub! 'M', 'Male'}
end

def pipe_date
 alpha = File.readlines('pipe.txt')
 alpha.each {|line| line.gsub! '-', '/'}
 alpha.each {|line| line.gsub! '|', ''}
 alpha.each {|line| line.gsub! 'M', 'Male'}
 alpha.sort_by { |str| Date.strptime(str[/\d+\/\d+\/\d+/], "%d/%m/%Y") } 
end

def pipe_des
  alpha = File.readlines('pipe.txt').sort { |a,b| b <=> a }
  alpha.each {|line| line.gsub! '-', '/'}
  alpha.each {|line| line.gsub! '|', ''}
  alpha.each {|line| line.gsub! 'M', 'Male'}
end

After looking around a bit, I wrote a test.rb file that looks like this, but when I run ruby test.rb, I get this error

MiniTest::Unit::TestCase is now Minitest::Test. From        /Users/pacloan/.rbenv/versions/2.1.2/lib/ruby/2.1.0/test/unit/testcase.rb:8:in   `<module:Unit>'
/Users/pacloan/.rbenv/versions/2.1.2/lib/ruby/2.1.0/test/unit.rb:676:in   `<class:Runner>': undefined method `_run_suite' for class `Test::Unit::Runner'   (NameError)

This is my test.rb file. I think my setup might be wrong. Can someone offer some insight on what I'm doing?

require_relative "app"
require 'minitest'
require 'test/unit'
require 'minitest/autorun'
Minitest::Test

class TestApp < Test::Unit::TestCase

  def test_read_files
    #assert something
    #expected output 
  end
end 

Upvotes: 1

Views: 314

Answers (2)

joelparkerhenderson
joelparkerhenderson

Reputation: 35453

You're doing everything the right way.

You have a few minor syntax items to fix.

When you require testing files, you'll typically only need minitest/autorun, not test/unit. (Minitest is typical of newer Ruby versions, test/unit is typical of older Ruby versions).

You can delete these lines:

require 'minitest'
require 'test/unit'

And this line:

Minitest::Test

Change this:

class TestApp < Test::Unit::TestCase

To this:

class TestApp < Minitest::Test

This is the new syntax.

You can verify your Ruby is current (version 2.2.x) like this:

$ ruby -v
ruby 2.2.0p0 (2014-12-25 revision 49005) [x86_64-darwin14]

You can verify your minitest gem is current (version 5.5.x) like this:

$ gem list minitest
minitest (5.5.1)

Heads up that many of the existing testing tutorials show the older syntax. If you try to run the older syntax on newer systems, you may see warnings and errors such as "TestCase is now Test" or "MiniTest is now Minitest".

Upvotes: 1

Prakash Murthy
Prakash Murthy

Reputation: 13067

Here is a very simple TDD exercise to start with:

Let's assume we need a method that takes a date string as an input and changes that string to have '/' instead of '-'.

i.e. Given 3-3-1985, the method should output 3/3/1985.

Let's write that as a test in first.rb file:

# first.rb
require 'test/unit' 

class TestApp < Test::Unit::TestCase
  test 'method to replace - with / in dates' do
    assert_equal "3/3/1985", format_date("3-3-1985")
  end 
end

Run it with ruby first.rb; it will give the following output:

Loaded suite first
Started
E
====================================================================================================================================
Error: test: method to replace - with / in dates(TestApp)
: NoMethodError: undefined method `format_date' for #    <TestApp:0x007ffc522493b0>
first.rb:5:in `block in <class:TestApp>'
====================================================================================================================================


Finished in 0.00177 seconds.
-----------------------------------------------------------------------    -------------------------------------------------------------
1 tests, 0 assertions, 0 failures, 1 errors, 0 pendings, 0 omissions, 0     notifications
0% passed
------------------------------------------------------------------------------------------------------------------------------------

As it says, there is no format_date method. To start with, add the method in the same file as follows:

# first.rb
require 'test/unit' 

class TestApp < Test::Unit::TestCase
  test 'method to replace - with / in dates' do
    assert_equal "3/3/1985", format_date("3-3-1985")
  end 
end

def format_date(given_date)
end

Run the test again with ruby first.rb

Now the error will be:

====================================================================================================================================
Failure: test: method to replace - with / in dates(TestApp)
first.rb:5:in `block in <class:TestApp>'
     2: 
     3: class TestApp < Test::Unit::TestCase
     4:   test 'method to replace - with / in dates' do
  => 5:     assert_equal "3/3/1985", format_date("3-3-1985")
     6:   end
     7: end
     8: 
<"3/3/1985"> expected but was
<nil>
====================================================================================================================================

So the method can be called, but it is returning nil instead of the expected 3/3/1985. Fix that by changing the method as follows:

def format_date(given_date)
  given_date.gsub! '-', '/'
end

Now when you run the test, the output will be:

Loaded suite first
Started
.

Finished in 0.00068 seconds.
------------------------------------------------------------------------------------------------------------------------------------
1 tests, 1 assertions, 0 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications
100% passed
------------------------------------------------------------------------------------------------------------------------------------

That is all. We started from a small failing test, and worked our way to a passing test, with the required functionality implemented.

Follow the same principles (write a small failing test / make it pass / repeat) for testing your file reading / converting exercise as well.

Upvotes: 0

Related Questions