应该匹配的ActiveRecord匹配器是否违反了“测试行为不实施”规则?

例如,如果我在我的规范中使用should validate_presence_of ,那只是测试我在模型中有validate_presence_of代码片段,那就是测试实现。 更重要的是,测试真正的问题并不是那个规范完全没用,“如果我没有填写某个字段,那么模型是否会成功保存?”

一些应该匹配的匹配器不测试实现,它们测试行为。 例如,查看allow_value的源allow_valuevalidate_presence_of使用的代码): #matches? 实际上将实例的属性设置为值,并检查是否会导致错误。 测试validation的所有shoulda-matchers匹配器(它的ActiveModel匹配器 )我看到的工作方式相同; 他们实际测试模型拒绝坏值。

请注意,如果您信任ActiveModel和ActiveRecord要进行全面测试,则匹配器测试行为或仅测试是否使用宏无关紧要。

unit testing模型的validation绝对有用。 假设您正在进行BDD并实现一个创建模型实例的简单表单。 您首先要编写验收测试(Cucumber或rspec场景),以测试正确填写表单并成功创建实例的快乐路径。 然后,您将编写第二个验收测试,其中包含表单中的错误,表明当表单中存在错误时,不保存任何实例,并使用相应的错误消息重新显示表单。

一旦你有错误路径场景可以在表单中做出一个错误,你会发现如果你为其他错误编写更多的错误路径场景,它们将是非常重复的 – 唯一的东西不同的是错误的字段值和错误消息。 然后你会有很多全栈场景,需要很长时间才能运行。 因此,不要写第一个错误路径方案。 相反,只需为可以捕获每个错误的validation编写unit testing。 现在大多数测试都很简单快速。 (这是从验收测试下降到unit testing以处理细节的一般BDD技术的具体示例。)

但是,我没有发现shoulda-matchers的ActiveRecord匹配器非常有用。 考虑到测试关联的匹配器,我发现我的验收测试总是迫使我将所有关联添加到我需要的模型中,并且在unit testing中没有什么可做的。 ActiveRecord匹配测试应用程序看不到的数据库function(例如have_db_index ),如果你是严格测试驱动的,那么我很有用,但我倾向于在那里松懈。 此外,对于它的价值,ActiveRecord匹配器不测试行为(这很难实现),只是使用了相应的宏。

我发现一个有用的匹配器ActiveRecord匹配器的一个例外是删除依赖对象。 我有时会发现没有验收规范已经迫使我处理删除对象时关联对象会发生什么。 ActiveRecord实现这种情况的方法是将:dependent选项添加到belongs_tohas_manyhas_one关联。 编写一个使用shoulda-matcher的belong_tohave_manyhave_one matcher和.dependent选项的.dependent是我所知道的最方便的测试方法。