例如,如果我在我的规范中使用should validate_presence_of
,那只测试我的模型中有validate_presence_of
段代码,以及我的测试实现。更重要的是,该规范对于测试真正的问题是完全没用的,这是“如果我没有填写某个字段,那么模型是否会成功保存?”#34;
答案 0 :(得分:10)
一些的shoulda-matchers匹配器不测试实现,他们测试行为。例如,查看the source for allow_value
(validate_presence_of
}用法):#matches?
实际上将实例的属性设置为值,并检查是否会导致错误。测试验证的所有测试匹配器(其ActiveModel matchers)都是以同样的方式工作的;他们实际测试模型拒绝坏的值。
请注意,如果您信任ActiveModel和ActiveRecord需要进行全面测试,那么匹配器测试行为或仅测试是否使用宏无关紧要。
单元测试模型的验证绝对有用。假设您正在进行BDD并实现一个创建模型实例的简单表单。您首先要编写验收测试(Cucumber或rspec场景),测试正确填写表单并成功创建实例的快乐路径。然后,您将编写第二个验收测试,其中包含一个表单中的错误,该错误表明当表单中存在错误时,不保存任何实例,并使用相应的错误消息重新显示表单。
一旦你有错误路径场景可以在表单中做出一个错误,你就会发现如果你为其他错误编写更多的错误路径场景,它们会非常重复 - 唯一不同的是错误的字段值和错误消息。然后你会有很多全栈场景,需要很长时间才能运行。所以不要写第一个错误路径方案。相反,只需为可以捕获每个错误的验证编写单元测试。现在大多数测试都很简单快速。 (这是从验收测试下降到单元测试以处理细节的一般BDD技术的具体示例。)
但是,我没有发现应该匹配的ActiveRecord matchers非常有用。考虑到测试关联的匹配器,我发现我的验收测试总是强迫我添加所有关联对于我需要的模型,在单元测试中没有什么可做的。 ActiveRecord匹配测试应用程序不可见的数据库功能(例如have_db_index
),如果你是严格测试驱动的,那么我很有用,但我倾向于在那里松懈。此外,对于它的价值,ActiveRecord匹配器不测试行为(这很难实现),只是使用了相应的宏。
我发现一个有用的匹配器ActiveRecord匹配器有用的一个例外是依赖对象的删除。我有时会发现没有接受规范已经迫使我处理一个对象时关联对象会发生什么被删除。 ActiveRecord实现此目的的方法是将:dependent
选项添加到belongs_to
,has_many
或has_one
关联。编写一个使用带有belong_to
或have_many
或have_one
匹配器和.dependent
匹配器的示例的示例是我所知道的最方便的测试方法。