如何删除 shoulda 测试中的重复项?

发布于 2024-07-06 00:22:46 字数 1189 浏览 6 评论 0原文

这就是我所得到的:

   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

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

Here is what I have:

   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

Clearly there is a lot of duplication there. Any thoughts on how to remove it, if only at the very least the context and the string?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

清旖 2024-07-13 00:22:46

测试/规格不是生产代码,因此干燥不是首要任务。

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

不要太担心规格是否干燥。 过分强调干测试往往会让事情变得更加困难,因为你必须跳转到事物的定义才能理解正在发生的事情。

Tests/specs are not production code and so being dry is not a priority.

The principle is that the specs should be clear to read, even if it means there is duplication of text across tests.

Don't be too concerned about specs being dry. Overemphasis of dry tests tends to make things more difficult as you have to jump around to the definitions of things to understand what is happening.

只是一片海 2024-07-13 00:22:46

测试中的重复不一定是一件坏事(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

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

Duplication in tests is not necessarily a Bad Thing(tm)

I suggest you read the following articles from 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

They make a convinving case for code duplication in the tests and keeping one assertion per test.

缘字诀 2024-07-13 00:22:46

这是针对您的具体问题的解决方案。 这个想法是创建一个类方法(如 Shoulda 的 context、setup 和 should)。

将重复封装在一个类方法中,接受所有不同的部分作为参数,如下所示:

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

Here's a solution to your specific problem. The idea is to create a class method (like Shoulda's context, setup and should).

Encapsulate the repetition in a class method accepting all varying parts as arguments like this:

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

Now you can call all these encapsulated tests with one liners (5-liners here for readability ;-)

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

In some cases, you may want to accept a block which could serve as your Shoulda setup.

苦妄 2024-07-13 00:22:46

就我个人而言,对于这个测试,我不会使用 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

Personally for this test, I wouldn't use Shoulda.
You can easily remove duplication by using dynamic method creation as follows:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文