12

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

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语法。根据迈伦大师赛:

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

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

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

4

2 回答 2

16

Myron Marston,核心 RSpec 提交者之一,在这里解释说你仍然应该使用

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
于 2013-05-22T02:34:45.420 回答
4

我认为这个问题没有正确答案,但我最近一直在重写我的测试套件,以摆脱should并专门使用expect语法,所以我会投入两分钱。我决定重新编写漂亮很大程度上是因为RSpec 的主要维护者Myron Marston写道

将来,我们计划更改默认值,以便只有 expect 可用,除非您明确启用 should。我们可能会在 RSpec 3.0 时尽快这样做,但我们希望给用户足够的时间来熟悉它。

他还评论说

我们没有删除“应该”的计划……但 expect 的陷阱更少,这是我为新项目推荐的语法。

我也同意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直接引用 in与间接引用 usingexpect(foo).to respond_to(:color)一样多的“重复” ,所以我对它并没有太分阶段,而且我对规范通常阅读的方式很感兴趣。但是,最终我认为这归结为只是首选写作风格的问题。subjectitexpect

于 2013-05-22T03:00:09.147 回答