Leveraging Test Data Builders in Cucumber Steps
Finding the balance between writing declarative scenarios and step reuse in Cucumber can be tricky at times. I have found leveraging a Test Data Builder library (often selling itself as an Object Mother library) helps in step reuse and prevents your scenarios from being overloaded with a lot of noise. There are many test data builder libraries out there to do this. Some of the popular ones are: Fixjour, FixtureReplacement, and FactoryGirl. (There are tons more on github.)
In the context of Cucumber these test builders work well when you need to create some records with default values in Given steps. Combined with the power of Cucumber step tables you can further leverage the builder pattern by providing the pertinent values to just the attributes that matter in each scenario. The code below works out of the box for builders that adhere to the “create_model_name” API, but can be easily adapted to any API. I have some thoughts on how to further leverage these builders in Cucumber along with Webrat but that is for another post. In the mean time, enjoy and fork away!
# step_definitions/builder_steps.rb
module BuilderStepHelpers
def create_model(model_name, attributes={})
send("create_#{model_name.gsub(' ','_')}",attributes)
end
end
World do |world|
world.extend BuilderStepHelpers
end
# Examples:
# Given the following widget exists:
# | Name | Price |
# | Foo | 20.00 |
# Given the following pets exist:
# | Pet Type | Months Old |
# | Dog | 23 |
# | Cat | 34 |
Given /^the following (.+?)(?:s|) exist(?:s|):$/ do |model_name, table|
table.hashes.each do |hash|
attributes = {}
hash.each { |k, v| attributes[k.gsub(' ','').underscore] = v }
create_model(model_name, attributes)
end
end
# Example:
# Given widgets named 'Foo', 'Bar', and 'Car' exist
Given /^(.+?)(?:s|) named (.+) exist$/ do |model_name, names|
names.extract_list.each do |name|
create_model(model_name, {:name => name})
end
end
# Example:
# Given an expensive widget exists (assumes you have a create_expensive_widget method)
# Given a widget exists
# Given 3 widgets exist
# Given 33 widgets exist
#
# Warning: this one can be a little too greedy at times so YMMV from project to project.
Given /^(a|an|\d+) (.+?)(?:s|) exist(?:s|)$/ do |ammount, model_name|
how_many = ammount =~ /a|an/ ? 1 : ammount.to_i
1.upto(how_many) { create_model(model_name) }
end
# support/string.rb
# Examples:
# "'Foo', 'Bar', and 'Jar'".extract_list # => ["Foo", "Bar", "Jar"]
# '"Dog", "Cat"'.extract_list # => ["Dog", "Cat"]
class String
def extract_list
self.scan((/['"](.*?)["']/)).flatten
end
end
You’re currently reading “Leveraging Test Data Builders in Cucumber Steps”, an entry on Ben Mabey
- Published:
- 02.05.09 / 4pm
- Tags:
- Post Navigation:
- « GitHub rocks!
Using Cucumber to Integrate Distributed Systems and Test Messaging »