5

我有一个应用程序需要大量数据(1000 条记录)来进行适当的测试。我发现获得一组体面的可测试、合理数据的唯一方法是使用我的生产 DB 的一个子集。我已将其转换为正常“测试/固定装置”位置的 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

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

4

5 回答 5

8

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

Fixtures 有一些问题,但是你可以做一些简单的事情来让它们更容易使用:

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

  2. 在测试的上下文中添加要测试的数据。这提高了测试的可读性,并避免在单元测试开始时编写“确保没有人弄乱固定装置”的健全性检查。

于 2008-10-23T12:03:08.003 回答
0

我要说的第一件事是:你在那个例子中测试什么?如果它是一个普通的 AR has_many 关联,那么我不会费心为它编写测试。您所做的只是测试 AR 是否有效。

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

于 2008-10-23T08:27:05.753 回答
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

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

于 2008-10-23T10:04:16.837 回答
0

卡梅伦说得对:你在测试什么?

什么样的系统需要 1000 条记录来测试?请记住,您的测试应该尽可能小,并且应该测试应用程序的行为。对于绝大多数这些测试,它不可能需要数千条记录。

对于需要对象关系的少量行为测试,请考虑模拟对象。您只会指定使测试通过所需的确切最小行为量,并且它们根本不会影响数据库,这将在您的测试套件中获得巨大的性能提升。跑得越快,人们跑得越频繁。

于 2008-10-25T12:55:20.250 回答
0

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

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

我还开始使用Shoulda,它与许多其他有用的东西一起使 ActiveRecord 关联测试变得如此简单:

should_have_many :children
should_belong_to :parent
于 2008-10-25T17:06:41.750 回答