我一直在为我的rails应用程序编写测试。我使用TestUnit进行单元测试和功能测试。我也使用黄瓜进行GUI测试。
但我发现http://www.dcmanges.com/blog/rails-unit-record-test-without-the-database说单位测试最好不要打到数据库。
我同意击中数据库需要相当长的时间。我已经使用spork来减少环境负荷。
测试rails应用程序的最佳做法是什么?
答案 0 :(得分:19)
这是你不应该对名字过于笼罩的情况之一。 Rails指的是将ActiveRecord模型作为“单元”测试运行的测试,主要是因为它们是框架直接支持的最低级别测试。根据测试传说,我承认我倾向于相当一致地进行切割,单元测试应该没有测试单元外部的依赖性;这意味着持久性机制,即数据库。
也就是说,在没有数据库的情况下测试任何复杂的ActiveRecord模型会很快让你想吃掉你的手。 Rails假定您使用数据库进行测试;这就是框架编写的方式。你可以尝试将所有东西都删除,但是你最终会失败,因为你最终会搞乱ActiveRecord关联的内部(不是为了胆小的人)。您可以尝试将所有与非持久性相关的代码提取到不使用数据库进行测试的单独模块中,但是您将创建相当多的不必要的复杂性。
不要试图打击框架。 ActiveRecord和ActionController在生产和测试中都有非常特定的预期用途模式。毕竟,Rails就是惯例。如果你遵循使用模式,你将会做更少的工作,并且变得更少受挫,而不是你为了坚持单元测试理想而对抗惯例。如果它让您感觉更好,请将您的ActiveRecord测试视为“模型”测试,并将您的功能测试视为“控制器”测试(这是rspec使用的术语,顺便说一句)。
所有这一切,您不应该在模型测试(或规范)中不必要地访问数据库。某些验证(例如唯一性)需要数据库,但大多数验证都不需要。许多与创建/保存回调和关联相关的操作都需要数据库,但其他操作则不需要。请注意您正在调用的操作正在进行中。
答案 1 :(得分:5)
单元测试不应该打到数据库。如果正确的数据可用(无论数据来自何处),他们应该测试方法是否按预期运行。因此,您应该根据需要进行存根/模拟,以确保每个单元测试都是隔离的。
然而,集成测试(例如,您可能使用Cucumber编写)应该将整个MVC堆栈绑定在一起,并且没有理由让那些不能访问数据库
答案 2 :(得分:1)
测试模型的“Rails方式”与“击中数据库的单元测试”的论点与说“好吧每个人都跳下桥,也许我应该这么做?”。
你应该认真分析你遵循的每个Rails惯例,因为事后看来“monolothic Rails应用程序”,如果他们遵循这个建议,他们就会有100多个模型进行集成测试。即使您使用慢速和快速标记规范,您也无法在“快速”类别中对模型进行单元测试(除非您也编写它们,在这种情况下,您可能正在测试太多)。
副作用:一个缓慢的单元测试套件需要一个小时。并且假设你坚持模型中的每一个方法,而不是将它抽象到不同的类,你处于更加痛苦的世界,因为你也需要为它们编写集成测试。
我知道无论你做什么,集成测试仍然会很慢,但是你能够解决这个问题的唯一方法就是巧妙地写下它们。
我正在尝试编写从HTTP请求中击中数据库的“请求规范”。并将它们用作我的“功能测试”。我编写的每个类,无论是服务,模型还是拥有什么,都有围绕公共方法的单元测试(显然存在数据库)。
答案 3 :(得分:0)
使用快速内存数据库进行单元测试。如果要测试“如果正确的数据可用,则按预期运行的方法”,最好使用与您的实际数据集非常相似的数据集。内存数据库可以包含非常小或相当大的数据集,具体取决于您的需要。 ruby-on-rails支持HSQLDB,通常用于单元测试。