这就是我所拥有的:
context "Create ingredient from string" do
context "1 cups butter" do
setup do
@ingredient = Ingredient.create(:ingredient_string => "1 cups butter")
end
should "return unit" do
assert_equal @ingredient.unit, 'cups'
end
should "return amount" do
assert_equal @ingredient.amount, 1.0
end
should "return name" do
assert_equal @ingredient.name, 'butter'
end
end
context "1 (18.25 ounce) package devil's food cake mix with pudding" do
setup do
@ingredient = Ingredient.create(:ingredient_string => "1 (18.25 ounce) package devil's food cake mix with pudding")
end
should "return unit" do
assert_equal @ingredient.unit, '(18.25 ounce) package'
end
should "return amount" do
assert_equal @ingredient.amount, 1.0
end
should "return name" do
assert_equal @ingredient.name, 'devil\'s food cake mix with pudding'
end
end
end
显然,那里有很多重复。关于如何删除它的任何想法,如果只是至少在上下文和字符串?
答案 0 :(得分:4)
这是您特定问题的解决方案。我们的想法是创建一个类方法(比如Shoulda的上下文,设置和应该)。
将重复封装在接受所有变化部分的类方法中,如下所示:
def self.should_get_unit_amount_and_name_from_string(unit, amount, name, string_to_analyze)
context string_to_analyze do
setup do
@ingredient = Ingredient.create(:ingredient_string => string_to_analyze)
end
should "return unit" do
assert_equal @ingredient.unit, unit
end
should "return amount" do
assert_equal @ingredient.amount, amount
end
should "return name" do
assert_equal @ingredient.name, name
end
end
end
现在,您可以使用一个衬垫调用所有这些封装测试(此处为5行,以提高可读性; - )
context "Create ingredient from string" do
should_get_unit_amount_and_name_from_string(
'cups',
1.0,
'butter',
"1 cups butter")
should_get_unit_amount_and_name_from_string(
'(18.25 ounce) package',
1.0,
'devil\'s food cake mix with pudding',
"1 (18.25 ounce) package devil's food cake mix with pudding")
end
在某些情况下,您可能希望接受可用作您的Shoulda设置的块。
答案 1 :(得分:2)
测试中的重复不一定是坏事(tm)
我建议你阅读Jay Field的以下文章
http://blog.jayfields.com/2007/06/testing-one-assertion-per-test.html
http://blog.jayfields.com/2008/05/testing-duplicate-code-in-your-tests.html
他们为测试中的代码重复提供了一个令人信服的案例,并且每次测试都保留一个断言。
答案 2 :(得分:1)
测试/规格不是生产代码,因此干燥不是优先考虑的事项。
原则是规范应该清晰易读,即使这意味着跨测试会出现文本重复。
不要太担心规格干燥。过度强调干燥测试往往会使事情变得更加困难,因为你必须跳到事物的定义来理解正在发生的事情。
答案 3 :(得分:0)
就此测试而言,我不会使用Shoulda。 您可以使用动态方法创建轻松删除重复,如下所示:
class DefineMethodTest < Test::Unit::TestCase
[{:string => '1 cups butter', :unit => 'cups', :amount => 1.0, :name => 'butter'},{:string => '1 (18.25 ounce) package devil's food cake mix with pudding', :unit => '(18.25 ounce) package', :unit => 1.0, :name => "devil's food cake mix with pudding"}].each do |t|
define_method "test_create_ingredient_from_string_#{t[:string].downcase.gsub(/[^a-z0-9]+/, '_')}" do
@ingredient = Ingredient.create(:ingredient_string => t[:string])
assert_equal @ingredient.unit, t[:unit], "Should return unit #{t[:unit]}"
assert_equal @ingredient.amount, t[:amount], "Should return amount #{t[:amount]}"
assert_equal @ingredient.name, t[:name], "Should return name #{t[:name]}"
end
end
end