October 29, 2016 · rspec ruby

Running and testing a single Ruby file

Say you are given a dice.rb file and asked to see if it works… what do you do?

# dice.rb
class Dice
  # Initializes with the number of dice to use.
  #
  # @param count [Integer] the number of dice to use
  def initialize(count = 2)
    @count = count
  end

  # Rolls all the dice and returns the total rolled.
  #
  # @return [Integer] the total rolled
  def roll
    1.upto(@count).reduce(0) {|sum| sum += rand(1..6) }
  end
end

The dice.rb file contains a single Dice class that has a roll method. You can read how it works, but how do you actually run it?

Option 1: Running it with IRB

The quick answer is: you can run the file using IRB (Interactive Ruby Shell).

irb -r ./dice.rb
=> irb(main):001:0>
Dice.new(2).roll
=> 8

The irb command starts a new interactive Ruby session. The -r flag instructs IRB to require in the dice.rb file when the shell is loaded. You can then interact directly with the included file.

If you make any changes to the file after loading the IRB shell, you need to reload it. Otherwise, you will only have access to the version of the file that was originally required.

You can reload the file using the load command.

irb -r ./dice.rb
=> irb(main):001:0>
# make change to file
load "./dice.rb"
=> true

Option 2: Running it with RSpec

It becomes tiresome using IRB when making changes to a file; you must continually reload the file and re-enter the command to check the results. That’s where RSpec comes in.

RSpec lets you set up a series of specs to run against your code. You can then re-run these commands as you make changes to see if you get the expected results. Setting up RSpec for a single file turns out to be simple.

First, make sure RSpec is installed.

gem install rspec

Then, add require "rspec/autorun" to the top of the file being tested. The require statement sets up the Ruby file to run the specs when executed.

Let’s look at the dice.rb file set up for specs.

require "rspec/autorun"

class Dice
  # Initializes with the number of dice to use.
  #
  # @param count [Integer] the number of dice to use
  def initialize(count = 2)
    @count = count
  end

  # Rolls all the dice and returns the total rolled.
  #
  # @return [Integer] the total rolled
  def roll
    1.upto(@count).reduce(0) {|sum| sum += rand(1..6) }
  end
end

describe Dice, ".roll" do
  it "it returns random total within expected range" do
    total = Dice.new(2).roll
    expect(total).to be_between(2, 12)
  end
end

At the bottom of the file is a single spec asserting that a Dice instance with two dice returns a random number between two and twelve.

The spec can be run using the ruby command.

ruby dice.rb
.

Finished in 0.00136 seconds (files took 0.1789 seconds to load)
1 example, 0 failures

Which option is better?

It really depends on your purpose. If you want to run a file that you have no intention of modifying, running it in IRB makes the most sense. However, if you need to edit the file and will be re-running the same commands over and over as you edit, then the RSpec method will save you time.