[rspec-users] Refactoring and using each

Jeroen van Dijk jeroentjevandijk at gmail.com
Wed Oct 8 07:01:25 EDT 2008


Hi all,

I'm new to this list and new to RSpec so I have been trying out RSpec the
last couple of days and I find it very a natural way of testing. So first of
all thanks for providing this framework.

Now, I have written some tests for my controllers and models and I saw
myself writing similar code, so I began refactoring and came up with the
following issue.

Here is a simple example of what I first wrote:

describe Example do

  it "should not be valid without attribute1" do
    Example.new(:attribute2 => "2").should_not be_valid
  end

  it "should not be valid without attribute2" do
    Example.new(:attribute1 => "1").should_not be_valid
  end
end

Which I rewrote into another working test:

######
module ExampleSpecHelper
  def required_valid_attributes
    {:attribute1 => "1", :attribute2 => "2"}
  end
end

describe Example do
   include ExampleSpecHelper
  [:attribute1, :attribute2].each do |attribute|
  before(:all) do
    @model_with_one_missing_attribute =
TextMessage.new(required_valid_attributes.except(attribute))
  end

  it "should not be valid without #{attribute}" do
    @model_with_one_missing_attribute.should_not be_valid
  end
end
#####

In this example in you might not see difference in lines of code, but
imagine you would have 10 attributes and 10 more tests for each attribute..
Now I rewrote this I was still not satisfied because I thought I would like
to use this same  approach for several models with different attributes
while keeping the logic of this test in one place. Unfortunately, I didn't
come that far because of this:

#this works:
describe Example do
include ExampleSpecHelper
  required_attributes = [:attribute1, :attribute2]
  required_attributes.each do |attribute|
  before(:all) do
    @model_with_one_missing_attribute =
TextMessage.new(required_valid_attributes.except(attribute))
  end

  it "should not be valid without #{attribute}" do
    @model_with_one_missing_attribute.should_not be_valid
  end
end

#However this which eventually will be more DRY, but does for some reason
not work?!
module ExampleSpecHelper
  ...
  def required_attributes
    [:attribute1, :attribute2]
  end
...
end

describe Example do
include ExampleSpecHelper
  required_attributes.each do |attribute|
  before(:all) do
    @model_with_one_missing_attribute =
TextMessage.new(required_valid_attributes.except(attribute))
  end

  it "should not be valid without #{attribute}" do
    @model_with_one_missing_attribute.should_not be_valid
  end
end


############

I don't understand why it does not work. In the last example
required_attributes is nil while the other methods from the helper module
such as 'required_valid_attributes' are available on an even lower level.
Why? I hope you understand why I'm trying to refactor it like this. If I can
do this I only need to define the required attributes for each model and use
it_should_behave_like "an AR model" to keep it DRY.

Hope someone can clarify this and that I haven't done something stupid!
Thanks!

Cheers,

Jeroen
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20081008/ecdebb96/attachment.html>


More information about the rspec-users mailing list