messaliberty

about hulor and us

[Ruby] How to use RSpec – 01 QuickStart

RSpec is one of ruby’s testing frameworks for BDD(Behavior Driven Development).

Install RSpec

% sudo gem install rspec

Quickstart

Directory Structure for sample program below.
put libraries into lib/ directory.
put spec(test) programs into spec/directory.

  • sample_project/
    • lib/sample.rb sample library to test
    • spec/
      • sample_spec.rb test program for sample.rb
      • spec_helper.rb common settings and functions for all tests.

Create directories

Create a project directory, create lib and spec directory in the project directory.

% mkdir sample_project
% cd sample_project
% mkdir lib
% mkdir spec

Create spec_helper.rb

sample_project/spec/spec_helper.rb :

# encoding: utf-8

require "rubygems"
require 'test/unit'
require "spec"
$LOAD_PATH << File.expand_path(File.join('..', 'lib'), File.dirname(__FILE__))

__END__

Needed "require 'test/unit'" before "require 'spec'" due to an error below with autospec.

/home/ice/.gem/ruby/1.8/gems/rspec-1.1.11/lib/spec.rb:25:in `exit?': undefined method `run?' for Test::Unit:Module (NoMethodError)
        from /home/ice/.gem/ruby/1.8/gems/rspec-1.1.11/lib/spec/runner.rb:192:in `register_at_exit_hook'
        from spec/messa/db/clawler/page_data_spec.rb:9

ref: http://www.ruby-forum.com/topic/170889

Create spec(test) program

Create a spec file first, not a library file.

This tests mix() method of Sample class in lib/sample.rb (not created yet).
Run this program like this:

% cd sample_project
% spec -c spec/sample_spec.rb

sample_project/spec/sample_spec.rb :

# -*- coding: utf-8 -*-

require File.expand_path(File.join('.', 'spec_helper'), File.dirname(__FILE__))
require 'sample' # for lib/sample.rb

describe Sample, "When mix two numbers," do
  before(:each) do
    @sample = Sample.new
  end

  it "should calculate as +" do
    @sample.mix(1, 1).should == 2
    @sample.mix(100, 11).should == 111
    @sample.mix(10, -109).should == -99
  end
end

RSpec extends Ruby Object, adds some methods for test.
should method checks objects.
You can use like this:

100.should == 100
1000.should >= 1
true.should be_true
false.should_not be_true

The method should()’s first parameter is called matcher.
I’ll describe these things next time.

Result :

% spec -c spec/sample_spec.rb
/usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require': no such file to load -- sample (LoadError)
        from /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
        from ./spec/sample_spec.rb:4
        from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.11/lib/spec/runner/example_group_runner.rb:14:in `load'
        from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.11/lib/spec/runner/example_group_runner.rb:14:in `load_files'
        from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.11/lib/spec/runner/example_group_runner.rb:13:in `each'
        from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.11/lib/spec/runner/example_group_runner.rb:13:in `load_files'
        from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.11/lib/spec/runner/options.rb:98:in `run_examples'
        from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.11/lib/spec/runner/command_line.rb:10:in `run'
        from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.11/bin/spec:4
        from /usr/bin/spec:19:in `load'
        from /usr/bin/spec:19

An error occured because lib/sample.rb file is not created yet.
This is test first. So, it’s OK!

Create library (testee) program

Error says “no such file to load — sample (LoadError)“.
Create sample_project/lib/sample.rb, this is still empty.
Run spec, then fail.

% spec -c spec/sample_spec.rb
./spec/sample_spec.rb:6: uninitialized constant Sample (NameError)
        from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.11/lib/spec/runner/example_group_runner.rb:14:in `load'
        from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.11/lib/spec/runner/example_group_runner.rb:14:in `load_files'
        from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.11/lib/spec/runner/example_group_runner.rb:13:in `each'
        from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.11/lib/spec/runner/example_group_runner.rb:13:in `load_files'
        from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.11/lib/spec/runner/options.rb:98:in `run_examples'
        from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.11/lib/spec/runner/command_line.rb:10:in `run'
        from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.11/bin/spec:4
        from /usr/bin/spec:19:in `load'
        from /usr/bin/spec:19

Error says “uninitialized constant Sample (NameError)“, there is no Sample class.
Create it like this:
sample_project/lib/sample.rb :

class Sample
end

Run spec.

% spec -c spec/sample_spec.rb
F

1)
NoMethodError in 'Sample When mix two numbers, should calculate as +'
undefined method `mix' for #<Sample:0xb7adbbac>
./spec/sample_spec.rb:12:

Finished in 0.061528 seconds

1 example, 1 failure

It says “undefined method `mix’ for #<Sample:0xb7adbbac>“, so define mix() method.
like this:

sample_project/lib/sample.rb

class Sample
  def mix(item1, item2)
  end
end

Result :

% spec -c spec/sample_spec.rb
F

1)
'Sample When mix two numbers, should calculate as +' FAILED
expected: 2,
     got: nil (using ==)
./spec/sample_spec.rb:12:

Finished in 0.026445 seconds

1 example, 1 failure

It says “expected: 2, got: nil (using ==)“.
Implement mix() like this:

sample_project/lib/sample.rb

class Sample
  def mix(item1, item2)
    return item1 + item2
  end
end

Run spec.

% spec -c spec/sample_spec.rb
.

Finished in 0.030934 seconds

1 example, 0 failures

Spec(test) passed.

Keep contitue like this cycle.

I’ll explain more about RSpec next time.

Current Sample Codes

sample_project/spec/spec_helper.rb

# encoding: utf-8

require "rubygems"
require 'test/unit'
require "spec"
$LOAD_PATH << File.expand_path(File.join('..', 'lib'), File.dirname(__FILE__))

sample_project/spec/sample_spec.rb

# -*- coding: utf-8 -*-

require File.expand_path(File.join('.', 'spec_helper'), File.dirname(__FILE__))
require 'sample' # for lib/sample.rb

describe Sample, "When mix two numbers," do
  before(:each) do
    @sample = Sample.new
  end

  it "should calculate as +" do
    @sample.mix(1, 1).should == 2
    @sample.mix(100, 11).should == 111
    @sample.mix(10, -109).should == -99
  end
end

sample_project/lib/sample.rb

class Sample
  def mix(item1, item2)
    return item1 + item2
  end
end
Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • email
  • Reddit
  • StumbleUpon
  • Technorati
  • MySpace
  • Tumblr
  • Yahoo! Buzz
  • Twitter

Related posts:

  1. [JRuby on Rails on GAE/J] how-to put rubygems into a jar file to get around file limitations GAE (Google App Engine) has a limit number to the...

Related posts brought to you by Yet Another Related Posts Plugin.

Leave a Reply