Catching errors, rspec basics

Trying to spec the following but don’t know if I’m using the right
matcher.
How do I spec? Plz, sugar on tops.

Audience.stats

  • should have a stats of 80 when passed a flux of 10
  • should return an error when passed a string (ERROR - 1)

TypeError in ‘Audience.stats should return an error when passed a
string’
String can’t be coerced into Fixnum
./audience.rb:11:in *' ./audience.rb:11:instats=’
./audience_spec.rb:29:

Finished in 0.006333 seconds

2 examples, 1 failure
monsterbox:spec andrew_wc_brown$

class Audience

attr_accessor :stats

def initialize(name = nil,value = nil)
@name ||= ‘all’
@value ||= value
end

def stats=(flux)
@stats = @value * flux / 0.025
end

def market_share
“The Market share is for #{@name} at a high of #{@stats}”
end

end

describe “Audience.stats” do

before :all do
@audience = Audience.new(nil,20)
end

it “should have a stats of 80 when passed a flux of 10” do
@audience.stats = 10
@audience.stats.should == 8000
end

it “should return an error when passed a string” do
@audience.stats = ‘Market Goblin’
@audience.stats.should raise_error
end
end

Are you looking for something like this

lambda { @audience.stats = ‘Market Goblin’ }.should raise_error

try it, does the same thing =’(

Hmmmm

I just ran this and 2 examples, 0 failures

class Audience

attr_accessor :stats

def initialize(name = nil,value = nil)
@name ||= ‘all’
@value ||= value
end

def stats=(flux)
@stats = @value * flux / 0.025
end

def market_share
“The Market share is for #{@name} at a high of #{@stats}”
end

end

describe “Audience.stats” do

before :all do
@audience = Audience.new(nil,20)
end

it “should have a stats of 80 when passed a flux of 10” do
@audience.stats = 10
@audience.stats.should == 8000
end

it “should return an error when passed a string” do
lambda {@audience.stats = ‘Market Goblin’}.should raise_error
end

end

Andrew WC Brown wrote:

lambda {@audience.stats = 'Market Goblin'}.should raise_error

end

I’ve seen lambda before but not sure what it does.

A lambda in ruby is like a block or a Proc. There are some differences
between them, but for this simple use you can just think of it as a
block of code that will be passed to the ‘raise_error’ matcher that then
runs that block of code checking to see if an Exception is raised when
it is ran. You can also pass in the specific exception type to be more
specific.

As a personal preference I like to alias lambda to ‘running’ in my
spec_helper.rb… I think this reads a lot better:
running {@audience.stats = ‘Market Goblin’}.should raise_error

For more on lambdas refer to the pickaxe. If you want more detailed
information of the subtle differences between them, Procs, blocks, and
methods check this out:
http://innig.net/software/ruby/closures-in-ruby.rb

-Ben

ohhhhh, I left in:
it “should return an error when passed a string” do
@audience.stats = ‘Market Goblin’
lambda {@audience.stats = ‘Market Goblin’}.should raise_error
end

when yours is:

it “should return an error when passed a string” do
lambda {@audience.stats = ‘Market Goblin’}.should raise_error
end

I’ve seen lambda before but not sure what it does.

Sematics… the method is never returning an error, it raises one. So
you can’t say @audience.stats=“dsfds” and expect to see an exception
returned right?
Since an exception is being raised you have to think of another way of
testing it aside from checking it’s return value… So you could do
something like:

an_error_was_raised = false
begin
@audience.stats = ‘Market Goblin’
rescue
an_error_was_raised = true
end
an_error_was_raised.should == true

I am not suggesting you do this. This is just to illustrate how you
would going about testing to see if an error was raised. The
raise_error matcher is slightly more complicated in order to be able to
ensure certain errors are raised but this is the general idea. So the
lambda does not return an error but the lambda is passed into the
matcher so it can perform a similar operation as the code above
illustrates. I hope that clarified things a bit.

Here is another example for good measure with a lambda involved… you
can then see how a lambda how be useful in this situation:

an_error_was_raised = false
my_code = lambda { @audience.stats = ‘Market Goblin’ }

begin
my_code.call
rescue
an_error_was_raised = true
end
an_error_was_raised.should == true

Better?

-Ben

On Jan 29, 2008 6:55 PM, Andrew WC Brown [email protected] wrote:

try it, does the same thing ='(

Shouldn’t be the exact same thing. What’s the whole error?

Also - what version of rspec? If trunk, do you have the latest (3268)?

lawl, David has been out of the loop a few e-mails.I left in an extra
line.

Thanks for the expansion Ben, adds much more clarity,

So if I understand correctly,
The following didn’t raise an error:

@audience.stats = ‘Market Goblin’
@audience.stats.should raise_error

because audience.stats didn’t return an error.

Where as lambda will return an error.