RSpec’Expect’语法和惯用属性规范

这应该有一个简单的答案,但我很难找到它(已检查RSpec文档,使用RSpec的EverydayRails测试,谷歌搜索结果)。 在我的模型规范中,我喜欢包括基本属性规范,如下所示:

describe Foo do describe "basic attributes" do before { @foo = create(:foo) } subject { @foo } it { should be_valid } it { should respond_to(:color) } it { should respond_to(:height) } it { should respond_to(:some_other_attribute) } it { should respond_to(:you_get_the_idea) } ... 

我喜欢这些规格,因为如果我的工厂和/或模型中存在某种错误,这些规格可以帮助我快速查明。

我已经将expect语法合并到所有其他规范中,我喜欢它的读取方式,但是如何在这里使用它? 一种选择可能是

 expect(@foo).to respond_to(:color) 

另一个可能是

 expect(it).to respond_to(:color) 

前者涉及使用should语法避免的重复,但后者对我来说很奇怪(可能只是我)。

我意识到这个问题更多的是关于风格而不是function*,但我们Ruby开发人员对风格很认真,我希望遵循标准实践并拥有可读的惯用代码。 任何帮助表示赞赏。 谢谢。

更新:顺便说一下,我提议的选项都没有实际工作。 他们都抛出undefined method 'expect'错误。 现在我真的很困惑!

考虑到错误,我意识到这是因为上面的should规范是在一行块内。 那么,混淆是如何用期望语法编写单行块? 鉴于此更新,问题非常关乎function性,我会很高兴听到别人的想法。

2015年4月更新

rspec > 3.0添加了另一种处理这些的方法,听起来像rspec ~> 4.0将取消应用语法。 每个迈伦大师赛:

一些用户对如何与期望语法相关以及是否可以继续使用它表示混淆。 它将继续在RSpec 3中可用(同样,无论您的语法配置如何),但我们还添加了一个与期望语法更加一致的备用API:

 describe Post do it { is_expected.to allow_mass_assignment_of(:title) } end 

is_expected非常简单地定义为expect(subject),并且还通过is_expected.not_to matcher支持负面期望。 […]
在RSpec 3中,我们保留了should语法,默认情况下它是可用的,但如果您在未明确启用它的情况下使用它,则会收到弃用警告。 这将为RSpec 4中默认禁用(或可能被提取到单独的gem)中铺平道路,同时最大限度地减少通过旧教程进入RSpec的新手的混乱。

Mylon Marston是RSpec核心提交者之一,他在此解释说你仍然应该使用

 it { should be_cool } 

如果你已经禁用了should语法,他提供了一个别名expect_it的解决方案:

 RSpec.configure do |c| c.alias_example_to :expect_it end RSpec::Core::MemoizedHelpers.module_eval do alias to should alias to_not should_not end 

有了这个,你可以这样写:

 describe User do expect_it { to be_valid } end 

我不认为这个问题的答案是正确的,但我最近一直在重写我的测试套件以摆脱should使用expect语法,所以我会把我的两分钱扔进去。我决定重新写得非常好,因为RSpec主要维护者Myron Marston 写道 :

将来,我们计划更改默认值,以便除非您明确启用should,否则只有expect可用。 我们可以在RSpec 3.0中尽快完成此操作,但我们希望为用户提供充足的时间来熟悉它。

他还评论说 :

我们没有计划删除“应该”…但期望有更少的陷阱,并且是我推荐用于新项目的语法。

我也同意Mark Rushakoff的回答,但我个人并不想创建这些别名只是为了保留一个it -block样式的语法。 所以,使用你的例子,我最初在这里写了一个像你的例子那样的模型规范:

 describe Foo do let(:foo) { create(:foo) } subject { foo } describe "model attributes" do it { should be_valid } it { should respond_to(:color) } it { should respond_to(:height) } it { should respond_to(:some_other_attribute) } it { should respond_to(:you_get_the_idea) } end # ... end 

我现在倾向于写它:

 describe Foo do let(:foo) { create(:foo) } specify "model attributes" do expect(foo).to be_valid expect(foo).to respond_to(:color) expect(foo).to respond_to(:height) expect(foo).to respond_to(:some_other_attribute) expect(foo).to respond_to(:you_get_the_idea) end # ... end 

我的观点是直接在expect(foo).to respond_to(:color)中引用foo expect(foo).to respond_to(:color)引用与使用it间接引用一个subject一样多“重复”,所以我不会过于分阶段,我正在变暖expect规格通常阅读的方式。 但是,最终我认为这只是一个首选写作风格的问题。