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

时间:2013-05-22 01:38:30

标签: ruby-on-rails rspec

这应该有一个简单的答案,但我很难找到它(已经检查了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语法避免的重复,但后者对我来说很奇怪(可能只是我)。

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

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

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

2015年4月更新

rspec > 3.0添加了另一种处理方法,听起来rspec ~> 4.0将取消should语法。 Per Myron Masters:

  

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

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

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

2 个答案:

答案 0 :(得分:16)

核心RSpec提交者之一Myron Marston解释here你仍然应该使用

it { should be_cool }

如果您已停用should语法,则他会为expect_it提供别名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

答案 1 :(得分:4)

我不认为这个问题的答案是正确的,但我最近一直在重写我的测试套件,以便远离should并专门使用expect语法,所以我会抛出我的两分钱。我决定重写,因为Myron Marston,RSpec主要维护者,wrote

  

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

他还commented

  

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

我也同意Mark Rushakoff的回答,但我个人并不想创建这些别名只是为了保留单个it - 块样式语法。因此,使用您的示例,我最初在这里以类似的形式编写了一个模型规范:

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

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