我应该如何在ruby中拆分大型单元测试?

时间:2010-06-22 20:02:22

标签: ruby unit-testing testing

我正在为我的一个导轨型号编写一些单元测试。它是一个大型模型,在某些情况下,我有很多方法的断言。我更喜欢使用带有rails'sactivesupport语法的普通测试/单元,所以我有一个这样的文件:

require 'test_helper'
class ItemTest < ActiveSupport::TestCase
  test "for_sale? should be true if cond 1..."
  test "for_sale? should be true if cond 2..."
  test "for_sale? should be true if cond 3..."
  test "for_sale? should be true if cond 4..."
  test "for_sale? should be false if cond 1..."
  test "for_sale? should be false if cond 2..."
  test "for_sale? should be false if cond 3..."
  test "for_sale? should be false if cond 4..."
end
每个方法的

等等。问题是测试变得越来越复杂,因为我不再依赖于setup(),因为每组测试的上下文对于每种方法都是如此不同。此外,在没有运行所有测试的情况下测试我正在使用的方法很困难。

其他人如何管理这样的大型测试用例?有最好的做法吗?

3 个答案:

答案 0 :(得分:1)

如果你想坚持测试/单位,我会推荐你​​。您不需要使用shoulda宏,但它将为您提供一个适用于此的非常好的功能:context。它允许您将单元测试分解为之前的单独部分,这些部分可以嵌套。

context "as a really cool user" do
  test "test number one..."
end

context "as a lame user" do
  test "test number two..."
end

从那里你可以继续使用所有测试/单位语法,或者如果你应该胜过你 - 你可以切换或混合匹配。

答案 1 :(得分:0)

我不知道这是不是最好的做法,但这就是我的工作。

我拥有创建特定对象的方法,例如setupcreate_credit_card_already_expiredcreate_credit_card_stolen,而不是让我想要在create_credit_card_valid中创建的所有对象。有时我将这些方法放入一个模块中,以便它们可以在不同的测试用例类之间共享。我还创建了自定义断言方法,例如assert_credit_card_rejected

所以我的示例代码是

require "test/unit"

module TestCreditCardHelper
  def assert_credit_card_rejected(credit_card, failure_message)
    assert credit_card.rejected?, failure_message #A real method might be more complicated
  end

  def create_credit_card_stolen
    CreditCard.new(:stolen => true)
  end

end

class TestCreditCard < Test::Unit::TestCase
  include TestCreditCardHelper

  def test_stolen_credit_card_rejected
    credit_card = create_credit_card_stolen
    assert_credit_card_rejected(credit_card, "Doesn't reject stolen credit cards")
  end
end

答案 2 :(得分:0)

单元测试应仅测试一件事。这听起来太多了。每种情况应该进行一次测试。

require 'test_helper'
class ItemTest_Condition1 < ActiveSupport::TestCase
  test "for_sale? should be true if cond 1..."
  test "for_sale? should be false if cond 1..."
end

class ItemTest_Condition2 < ActiveSupport::TestCase
  test "for_sale? should be true if cond 2..."
  test "for_sale? should be false if cond 2..."
end
class ItemTest_Condition3 < ActiveSupport::TestCase
  test "for_sale? should be true if cond 3..."
  test "for_sale? should be false if cond 3..."
end
...