Rails测试:固定装置,工厂和魔术数字

时间:2008-10-22 23:58:43

标签: ruby-on-rails unit-testing testing yaml

我有一个需要相当多数据(1000个记录)的应用程序来进行适当的测试。我发现获得一组可测试的,合理的数据的唯一方法是使用我的生产数据库的子集。我在正常的`test / fixtures'位置将它转换为YAML灯具。

这有效,但是现在我有一堆看似脆弱的测试和断言,这取决于它们是满足条件X的特定数量的记录......

例如

def test_children_association
  p = Parent.find(1)
  assert_equal 18, p.children.count, "Parent.children isn't providing the right records"
end

这对我来说似乎不是一个好主意,但是我不确定是否有更好/可接受的方式来测试需要大量数据层次结构的应用程序。

5 个答案:

答案 0 :(得分:8)

测试中的幻数不是反模式。您的测试需要非常简单,以至于您无需测试它们。这意味着你将拥有一些神奇的数字。这意味着当您更改少量功能时,您的测试将会中断。这很好。

灯具有some problems,但您可以采取一些简单的方法来使它们更易于使用:

  1. 只有您的灯具中的基线数据,大多数测试需要但不关心的数据类型。这将涉及预先投入时间,但最好早点承担痛苦,而不是在项目的整个生命周期中编写糟糕的单元测试。

  2. 在测试环境中添加要测试的数据。这样可以提高测试的可读性,并使您免于在单元测试开始时写下“确保没有人弄乱灯具”的健全性检查。

答案 1 :(得分:0)

我要说的第一件事是:你在那个例子中测试的是什么?如果它是普通的AR has_many关联,那么我就不会为它编写测试了。你正在做的只是测试AR的工作原理。

更好的例子可能是您有一个非常复杂的查询,或者在获取子记录列表时涉及其他处理。当你找回它们,而不是测试计数时,你可以遍历返回的列表并验证孩子是否符合你正在使用的标准。

答案 2 :(得分:0)

我发现在这种情况下最有用的不是使用灯具,而是在运行中构建数据库对象

def test_foo
   project = Project.create valid_project.merge(....)
   *do assertions here*
end

在我的test_helpers中我有一堆方法:

def valid_project
   { :user_id => 23, :title => "My Project" }
end

def invalid_project
   valid_project.merge(:title => nil)
end

我发现必须构建大量测试对象的痛苦使我自然地设计出更简单,更通用的类结构。

答案 3 :(得分:0)

Cameron是对的:你在测试什么?

什么样的系统需要1000个记录来测试?请记住,您的测试应该尽可能小,并且应该测试应用程序行为。绝大多数测试都无法获得数千条记录。

对于需要对象关系的一些行为测试,请考虑模拟对象。您只会指出测试通过所需的确切最小行为量,并且它们根本不会触及数据库,这将在您的测试套件中获得巨大的性能提升。运行得越快,人们运行它的频率就越高。

答案 4 :(得分:0)

我可能在这里有一个独特的情况,但我确实需要相当多的记录来测试这个应用程序(我把它降到150左右)。我正在分析历史数据,并且有很多级has_many。我的一些方法在几个表中执行自定义SQL查询,我可能最终修改为使用ActiveRecord.find,但我需要先运行测试。

无论如何,我最终使用了一些 ruby​​代码来创建灯具。该代码包含在我的test_helper中;它检查测试数据库以查看数据是否过时(基于时间条件)和擦除,在程序上重新创建记录。在这种情况下,以程序方式创建它可以让我知道我正在测试应该的数据是什么,哪个比使用生产数据的子集更安全并希望数字我计算的第一次是我将来应该测试的。

我也转而使用Shoulda以及许多其他有用的东西使ActiveRecord Association测试变得如此简单:

should_have_many :children
should_belong_to :parent