Reputation: 336
I have a class called Grid:
class Grid
attr_reader :rows, :columns
def initialize(rows=20, columns=20)
@rows = rows
@columns = columns
end
end
I want to test that the rows and columns fields return 20 by default and return whatever integer is supplied otherwise. I don't know the best way to do this.
I "solved" this by creating two Grid instances. One has supplied values for rows and columns. The other one does not have supplied values and thus uses the default values of 20.
require_relative 'spec_helper.rb'
describe Grid do
let(:grid) {Grid.new(15, 15)}
let(:gridNoParameters) {Grid.new()}
subject { grid }
describe "#rows" do
its(:rows) { should eq(15) }
context "when parameter not supplied" do
subject { gridNoParameters }
its(:rows) { should eq(20) }
end
end
describe "#columns" do
its(:columns) { should eq(15) }
context "when parameter not supplied" do
subject { gridNoParameters }
its(:columns) { should eq(20) }
end
end
Is this the best way to test? Any help is appreciated as I am pretty new to Rspec and test driven development.
Upvotes: 2
Views: 1905
Reputation: 33954
I think your approach is fine.
This particular test strikes me as a bit defensive/paranoid, but if it's critical that a test fails if/when someone accidentally changes or removes the default values, then I guess this test is fine.
Testing constructors is always a little weird to me, if all the constructor does is copy the input parameters to the instance variables. It borders on testing that the =
operator in Ruby actually works, which is a bit silly. It also borders on what I call, "testing against typos," where the test will only fail if a developer makes a blindingly obvious mistake or removes a default from a method without thinking it through. The thing is, I don't believe that any amount of testing can successfully protect against sloppiness.
There are more complex situations where I might be this careful, but the class you're presenting as an example here is so simple and so straightforward that I don't think it needs anything more than this, personally.
Upvotes: 0
Reputation: 1026
I would lay out the spec like this:
describe Grid do
context "#initialize" do
context "with parameters" do
let(:grid) { Grid.new(15, 15) }
it "should use specified values" do
expect(grid.rows).to eq 15
expect(grid.columns).to eq 15
end
end
context "without parameters" do
let(:grid) { Grid.new }
it "should use defaults" do
expect(grid.rows).to eq 15
expect(grid.columns).to eq 15
end
end
end
end
Take a look at BetterSpecs for ideas how to organize specs, and to use expect notation, etc. I'm not a huge fan of using subject
here, but it's up to you, as it is personal preference.
Upvotes: 3