nland
nland

Reputation: 669

How to test elements in an array rspec

I am doing some simple TDD and I'm looking to test some elements in an array that I have, and I'm having a little bit of trouble. Here's what I have thus far as far as my tests:

require_relative '../divisible'

describe Divisible do

  before do
    subject = Divisible.new
  end

  describe 'find_numbers' do

    it "stores a number divisible by 3 and 5 in an array" do
      subject.find_numbers(3).should == 1
      subject.find_numbers(6).should == 3
      subject.find_numbers(12).should == 6
    end

    it "calls the sum_numbers function" do
      subject.find_numbers(3).should_receive(:sum_numbers).with(3)
    end
  end
end

Here is my class:

class Divisible

  def find_numbers(num)
    divisible_numbers = Array.new

    for i in 1..num
      if (i % 3) == 0 || (i % 5) == 0
        divisible_numbers.push(i)
      end
    end
    sum_numbers(divisible_numbers)
    return divisible_numbers.count
  end

  def sum_numbers(array)
  end
end

Ok, so what I want is to test the elements in the divisible_numbers array. I'm having some trouble accessing that array from the test to verify that the numbers I want are actually being stored in that array. Any suggestions as to how to test this? I realize that those first tests will need to be re-written, but I'm hoping that by testing the array itself, then I don't have to worry about the tests breaking down the road.

Side note: I'm also looking for a way to be sure that my find_numbers function calls my sum_numbers function with rspec. Ideally I would like to test that the function would be called before having to create the sum_numbers function. It seems as though I would be using a stub, but that concept has not fully settled with me, so any pointers here would be awesome! Thanks.

Upvotes: 0

Views: 1904

Answers (2)

Sascha Kaestle
Sascha Kaestle

Reputation: 1293

I would advise to move divisible_number to an instance_var:

class Divisible
  attr_accessors :divisible_numbers

  def initialize
    self.divisible_numbers = []
  end


  def find_numbers(num)
    (1..num).each do |current_num|
      if (current_num % 3) == 0 || (current_num % 5) == 0
        self.divisible_numbers.push(i)
      end
    end

    self.sum_numbers
    self.divisible_numbers.count
  end

  def sum_numbers
    # do whatever with self.divisible_number
  end
end

this way you can make your tests more specific:

require_relative '../divisible'

describe Divisible do
  before(:each) do
    subject = Divisible.new
  end

  describe 'find_numbers' do
    it "returns 1 number divisible by 3 or 5 between 1..3" do
      subject.find_numbers(3).should == 1
      subject.divisible_numbers.should be == [3]
    end

    it "returns 3 number divisible by 3 or 5 between 1..6" do
      subject.find_numbers(6).should == 3
      subject.divisible_numbers.should be == [3, 5, 6]
    end

    it "returns 6 number divisible by 3 or 5 between 1..12" do
      subject.find_numbers(6).should == 3
      subject.divisible_numbers.should be == [3, 5, 6, 9, 10, 12]
    end

    it "calls the sum_numbers function" do
      subject.should_receive(:sum_numbers).once
      subject.find_numbers(3)
    end
  end
end

i guess the test thing is a debatable, because it gets verbose.

Upvotes: 2

tpbowden
tpbowden

Reputation: 2090

You could just check that the right array is being passed into the sum_numbers method. At the minute your test for this is not checking the right thing I don't think. It should look something like this:

it "calls the sum_numbers function" do
    subject.should_receive(:sum_numbers).with([3])
    subject.find_numbers(3)
end

This way you are testing each part of your method are doing what is required.

Upvotes: 0

Related Questions