2

这是我所拥有的:

   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

显然那里有很多重复。关于如何删除它的任何想法,如果至少是上下文和字符串?

4

4 回答 4

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 设置的块。

于 2008-09-22T13:12:45.530 回答
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

他们为测试中的代码重复提供了一个令人信服的案例,并为每个测试保留一个断言。

于 2008-09-22T08:27:35.203 回答
1

测试/规范不是生产代码,因此干燥不是优先事项。

原则是规范应该清晰易读,即使这意味着测试中存在重复的文本。

不要太担心规格干燥。过分强调干测试往往会使事情变得更加困难,因为您必须跳到事物的定义以了解正在发生的事情。

于 2008-09-23T05:38:34.350 回答
0

对于这个测试,我个人不会使用Shouda。您可以使用动态方法创建轻松删除重复,如下所示:

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
于 2008-09-22T05:54:54.977 回答