我该如何删除应试测试中的重复项?
时间:2020-03-06 14:31:29 来源:igfitidea点击:
这是我所拥有的:
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
显然那里有很多重复。如果至少将上下文和字符串删除,是否有任何关于如何删除它的想法?
解决方案
就个人而言,我不会使用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
测试中的重复不一定是一件坏事(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
他们为测试中的代码重复提供了令人信服的理由,并为每个测试保留了一个断言。
这是我们特定问题的解决方案。这个想法是创建一个类方法(如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设置的块。
测试/规格不是生产规范,因此干燥不是重点。
原则是规范应该清晰易读,即使这意味着测试之间文本重复。
不必太担心规格干燥。由于我们不得不跳到事物的定义以了解正在发生的事情,因此过分强调干燥测试会使事情变得更加困难。