I'm impressed at the brevity and usefulness of Cucumber's Scenarios, they're a great way to test a load of different cases.
e.g. example Cucumber scenario
Feature: Manage Users
In order to manage user details
As a security enthusiast
I want to edit user profiles only when authorized
Scenario Outline: Show or hide edit profile link
Given the following user records
| username | password | admin |
| bob | secret | false |
| admin | secret | true |
Given I am logged in as "<login>" with password "secret"
When I visit profile for "<profile>"
Then I should <action>
Examples:
| login | profile | action |
| admin | bob | see "Edit Profile" |
| bob | bob | see "Edit Profile" |
| | bob | not see "Edit Profile" |
| bob | admin | not see "Edit Profile" |
(Code taken from Ryan Bates' More on Cucumber Screencast)
Is there an equivalent in RSpec?
I'd like to do the same thing in RSpec and to DRY up my code by reducing different tests down to a row in a scenario table.
Although I could write the code to do this myself, the fact that I'm considering it makes me wonder two things
If this is useful it probably already exists in which case how do I use it?
If it doesn't exist it suggests it shouldn't be done this way and that I'm approaching the problem incorrectly, how should I rethink my approach to RSpec?
Which answer is right and if it is useful, how do I do it?
The main difference between RSpec and Cucumber are the business readability factor. Cucumber's main draw is that the specification (features) are separate from the test code, so your product owners can provide or review the specification without having to dig through code.
RSpec is a testing tool for Ruby, created for behavior-driven development (BDD). It is the most frequently used testing library for Ruby in production applications. Even though it has a very rich and powerful DSL (domain-specific language), at its core it is a simple tool which you can start using rather quickly.
Installing RSpecBoot up your terminal and punch in gem install rspec to install RSpec. Once that's done, you can verify your version of RSpec with rspec --version , which will output the current version of each of the packaged gems. Take a minute also to hit rspec --help and look through the various options available.
Try the following approach. I like the way it turned out.
describe StateDateMethods do
before :each do
@product = OpenStruct.new
@product.extend StateDateMethods
end
def parse_date(unparsed_date_value)
unless unparsed_date_value.nil?
DateTime.strptime(unparsed_date_value, '%m/%d/%Y')
end
end
context '#pre_order?' do
examples = [
# [visible_on, pre_order_on, for_sale_on] => method_result
{ :inputs => [nil, nil, nil], :expected => false },
{ :inputs => ['1/1/2001', nil, nil], :expected => false },
{ :inputs => ['1/1/2001', '1/1/2001', nil], :expected => true },
{ :inputs => ['1/1/2001', '1/2/2001', nil], :expected => true },
{ :inputs => ['1/1/2001', '1/1/2001', '1/2/2001'], :expected => false },
{ :inputs => ['1/1/2001', '1/1/2001', '1/1/3001'], :expected => true },
{ :inputs => ['1/1/2001', '1/1/3001', '1/2/3001'], :expected => false },
{ :inputs => ['1/1/3001', '1/1/3001', '1/2/3001'], :expected => false },
{ :inputs => ['1/1/2001', nil, '1/1/2001'], :expected => false },
{ :inputs => ['1/1/2001', nil, '1/1/3001'], :expected => false }
]
examples.each do |example|
inputs = example[:inputs]
it "should return #{example[:expected].inspect} when visible_on == #{inputs[0].inspect}, pre_order_on == #{inputs[1].inspect}, for_sale_on == #{inputs[2].inspect}" do
@product.visible_on = parse_date(inputs[0])
@product.pre_order_on = parse_date(inputs[1])
@product.for_sale_on = parse_date(inputs[2])
@product.pre_order?.should == example[:expected]
end
end
end
end
I think this gives the best of both worlds, because it keeps me from repeating myself, and it creates a different test for each condition.
Here's what a failure looks like:
....F.....
Failures:
1) StateDateMethods#pre_order? should return false when visible_on == "1/1/2001", pre_order_on == "1/1/2001", for_sale_on == "1/2/2001"
Failure/Error: @product.pre_order?.should == example[:expected]
expected: false
got: true (using ==)
# ./spec_no_rails/state_date_methods_spec.rb:40:in `block (4 levels) in <top (required)>'
Finished in 0.38933 seconds
10 examples, 1 failure
Failed examples:
rspec ./spec_no_rails/state_date_methods_spec.rb:35 # StateDateMethods#pre_order? should return false when visible_on == "1/1/2001", pre_order_on == "1/1/2001", for_sale_on == "1/2/2001"
And here's what all green looks like:
..........
Finished in 0.3889 seconds
10 examples, 0 failures
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With