Rails 3.1,RSpec:测试模型验证
我已经开始了 Rails 中的 TDD 之旅,并且遇到了一个关于模型验证测试的小问题,我似乎找不到解决方案。假设我有一个用户模型
class User < ActiveRecord::Base
validates :username, :presence => true
end
和一个简单的测试
it "should require a username" do
User.new(:username => "").should_not be_valid
end
,这可以正确测试存在验证,但如果我想更具体怎么办?例如,在错误对象上测试 full_messages。
it "should require a username" do
user = User.create(:username => "")
user.errors[:username].should ~= /can't be blank/
end
我对初始尝试(使用 should_not be_valid)的担忧是 RSpec 不会生成描述性错误消息。它只是说“预期有效?返回 false,得到 true”。然而,第二个测试示例有一个小缺点:它使用 create 方法而不是 new 方法来获取错误对象。
我希望我的测试能够更具体地说明他们正在测试的内容,但同时不必接触数据库。
有人有任何意见吗?
I have started my journey with TDD in Rails and have run into a small issue regarding tests for model validations that I can't seem to find a solution to. Let's say I have a User model,
class User < ActiveRecord::Base
validates :username, :presence => true
end
and a simple test
it "should require a username" do
User.new(:username => "").should_not be_valid
end
This correctly tests the presence validation, but what if I want to be more specific? For example, testing full_messages on the errors object..
it "should require a username" do
user = User.create(:username => "")
user.errors[:username].should ~= /can't be blank/
end
My concern about the initial attempt (using should_not be_valid) is that RSpec won't produce a descriptive error message. It simply says "expected valid? to return false, got true." However, the second test example has a minor drawback: it uses the create method instead of the new method in order to get at the errors object.
I would like my tests to be more specific about what they're testing, but at the same time not have to touch a database.
Anyone have any input?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
恭喜您通过 ROR 努力进入 TDD,我保证一旦您开始行动,您就不会回头。
最简单的快速而肮脏的解决方案是在每次测试之前生成一个新的有效模型,如下所示:
但我建议您为所有模型设置工厂,它会自动为您生成一个有效模型,然后您可以使用个别属性,看看你是否验证。我喜欢使用 FactoryGirl 来实现此目的:
基本上一旦设置完毕,您的测试将如下所示:
这是一个很好的railscast,解释了这一切比我更好:
更新:自版本 3.0< /a> 工厂女孩的语法已更改。我修改了示例代码以反映这一点。
CONGRATULATIONS on you endeavor into TDD with ROR I promise once you get going you will not look back.
The simplest quick and dirty solution will be to generate a new valid model before each of your tests like this:
BUT what I suggest is you set up factories for all your models that will generate a valid model for you automatically and then you can muddle with individual attributes and see if your validation. I like to use FactoryGirl for this:
Basically once you get set up your test would look something like this:
Here is a good railscast that explains it all better than me:
UPDATE: As of version 3.0 the syntax for factory girl has changed. I have amended my sample code to reflect this.
测试模型验证(以及更多活动记录)的一种更简单的方法是使用像 shoulda 或卓越。
他们将允许进行如下测试:
An easier way to test model validations (and a lot more of active-record) is to use a gem like shoulda or remarkable.
They will allow to the test as follows:
试试这个:
Try this:
在新版本的rspec中,你应该使用expect而不是should,否则你会收到警告:
in new version rspec, you should use expect instead should, otherwise you'll get warning:
我传统上是在功能或请求规范中处理错误内容规范。因此,举例来说,我有一个类似的规范,我将在下面对其进行浓缩:
功能规范示例
然后,我让我的模型规范测试某些内容是否有效,然后我的功能规范测试确切的错误消息的输出。仅供参考,这些功能规范需要 Capybara,可以在此处找到。
I have traditionally handled error content specs in feature or request specs. So, for instance, I have a similar spec which I'll condense below:
Feature Spec Example
So then, I have my model spec testing whether something is valid, but then my feature spec which tests the exact output of the error message. FYI, these feature specs require Capybara which can be found here.
就像 @nathanvda 所说,我会利用 Thoughtbot 的 Shoulda Matchers gem。通过这种摇摆,您可以按照以下方式编写测试,以测试是否存在以及任何自定义错误消息。
Like @nathanvda said, I would take advantage of Thoughtbot's Shoulda Matchers gem. With that rocking, you can write your test in the following manner as to test for presence, as well as any custom error message.
有点晚了,但如果你不想添加 shoulda 匹配器,这应该适用于 rspec-rails 和factorybot:
A little late to the party here, but if you don't want to add shoulda matchers, this should work with rspec-rails and factorybot: