RSpec 3.5 已发布!

Sam Phippen, Myron Marston 和 Jon Rowe

2016 年 7 月 1 日

RSpec 3.5 刚刚发布!鉴于我们对 语义版本控制 的承诺,对于任何已经使用 RSpec 3 的人来说,这应该是一个简单的升级,但如果我们确实引入了任何回归,请告知我们,我们将尽快发布一个包含修复程序的补丁版本。

RSpec 仍然是一个社区驱动的项目,来自世界各地的贡献者参与其中。此版本包含来自 50 多位不同贡献者的 600 多个提交和 150 个合并的拉取请求!

感谢所有帮助使此版本成为现实的人!

重要变更

核心:config.when_first_matching_example_defined

我们通常建议您避免在 spec_helper.rb 中放置仅由部分规范需要的设置逻辑,这样可以最大限度地减少运行隔离单元规范的启动时间。相反,这种设置逻辑可以放在 spec/support 中的某个文件中。需要它的规范文件可以然后要求支持文件并标记示例组以选择加入任何相关的钩子和模块包含,例如

require 'support/db'

RSpec.describe SomeClassThatUsesTheDB, :db do
  # ...
end

这可以工作,但始终感觉很不理想,因为需要 require:db 标签才能使其工作。这是每个使用 DB 的规范文件中都会发生的重复。如果我忘记在使用 DB 的规范文件中放入 require 'support/db' 行,我可能会遇到这样的情况:规范文件在单独运行时失败,但在与整个套件一起运行时通过(因为其他规范文件加载了支持文件)。

RSpec 3.5 包含一个新的钩子,在这种情况下效果很好。您无需在每个需要它的规范文件中都要求 support/db,而是可以配置 RSpec,使其在定义了任何标记为 :db 的示例时加载它

RSpec.configure do |config|
  config.when_first_matching_example_defined(:db) do
    require 'support/db'
  end
end

此新的 when_first_matching_example_defined 钩子会在定义第一个具有匹配元数据的示例时立即触发,允许您根据元数据配置需要加载的内容。当然,这个新的钩子并不局限于此用例,但它是我们期望看到它使用的主要方法之一。

核心:config.filter_run_when_matching

RSpec 元数据系统的一个常见用途是焦点过滤。在 RSpec 3.5 之前,您会像这样配置它

RSpec.configure do |config|
  config.filter_run :focus
  config.run_all_when_everything_filtered = true
end

然后,您可以用 :focus 标记一个示例或组,让 RSpec 仅运行您标记的内容。当没有任何内容标记为 :focus 时,您希望 RSpec 忽略此过滤器,因此 run_all_when_everything_filtered = true 选项使其执行此操作。

不幸的是,run_all_when_everything_filtered 全局应用于所有过滤(不仅仅是 :focus 过滤),并且它在某些情况下会产生一些令人惊讶的行为。(有关一个示例,请参阅 此问题)。我们意识到,能够将 :focus 设置为条件过滤器会更有意义,因此在 RSpec 3.5 中,您可以这样做

RSpec.configure do |config|
  config.filter_run_when_matching :focus
end

使用此配置,:focus 过滤仅在任何示例或组标记为 :focus 时才适用。它还使配置更短、更简单!

核心:按命令行中指定的顺序加载规范文件

RSpec 3.5 现在按命令行参数的顺序加载规范文件和目录。这提供了一种简单的方法,可以以一次性方式对事物进行排序。例如,对于特定的规范运行,如果您希望快速单元规范在缓慢的验收规范之前运行,则可以像这样运行 RSpec

$ rspec spec/unit spec/acceptance --order defined

--order defined 部分仅在您已配置 RSpec 通常随机排序事物时才需要(我们建议将其作为您的默认值)。

核心:共享示例组包含更改

RSpec 长期以来一直支持共享上下文的概念,即为共享上下文帮助程序和钩子而定义的共享示例组。您可以像这样定义共享上下文

RSpec.shared_context "DB support" do
  let(:db) { MyORM.database }

  # Wrap each example in a transaction...
  around do |ex|
    db.transaction(:rollback => :always, &ex)
  end

  # Interleave example begin/end messages in DB logs so it
  # is clear which SQL statements come from which examples.
  before do |ex|
    db.logger.info "Beginning example: #{ex.metadata[:full_description}"
  end
  after do |ex|
    db.logger.info "Ending example: #{ex.metadata[:full_description}"
  end
end

要使用此共享上下文,您可以使用 include_context 在组中显式包含它

RSpec.describe MyModel do
  include_context "DB support"
end

我们还支持使用匹配元数据在组中隐式包含共享上下文的方法

RSpec.shared_context "DB support", :db do
  # ...
end

# ...

RSpec.describe MyModel, :db do
  # ...
end

这种方法可以正常工作,但存在几个重大问题

在 RSpec 3.5 中,我们通过一些更改纠正了这些问题。

新 API:config.include_context

您现在可以在 RSpec.configure 块中定义共享上下文包含

RSpec.configure do |config|
  config.include_context "DB support", :db
end

这与模块包含的现有 config.include API 一致,提供了一种基于元数据包含共享上下文的方法,这种方法不那么令人惊讶,并且可以轻松地将共享上下文包含在所有示例组中(只需不要传递元数据参数)。

新配置选项:config.shared_context_metadata_behavior

我们还添加了一个配置选项,允许您确定如何处理共享上下文元数据

RSpec.configure do |config|
  config.shared_context_metadata_behavior = :trigger_inclusion
  # or
  config.shared_context_metadata_behavior = :apply_to_host_groups
end

以前的值(:trigger_inclusion)是默认值,仅出于向后兼容性而存在。它将传递给 RSpec.shared_context 的元数据与 RSpec 3.4 及更早版本中的处理方式完全相同:它会触发包含在具有匹配元数据的组中。我们计划在 RSpec 4 中删除对它的支持。

后者的值(:apply_to_host_groups)选择加入新行为。它不会触发包含在具有匹配元数据的组中,而是将元数据应用于宿主组。例如,您可以通过标记共享上下文来关注使用 DB 的所有组

RSpec.shared_context "DB support", :focus do
  # ...
end

期望:respond_to 匹配器的关键字参数支持。

关键字参数已经是一项稳定的语言特性有一段时间了,但 RSpec 缺乏对我们各种匹配器中对关键字参数放置期望的支持。

在 rspec-expectations 3.5 中,我们添加了对检查对象是否响应使用关键字参数的方法的支持。现在,您将能够检查方法的响应签名以查找特定关键字以及传统参数的数量。

expect(my_object).to respond_to(:find).with_keywords(:limit, :offset)
expect(my_object).to respond_to(:find).with(1).argument.and_keywords(:limit, :offset)

我们还在扩展匹配器的现有功能,添加了检查一系列参数或除特定数量之外的无限参数的能力,例如

expect(my_object).to respond_to(:build).with(2..3).arguments
expect(my_object).to respond_to(:build).with_unlimited_arguments

非常感谢 Rob Smith 为将此作为 RSpec 的一部分所付出的努力。

期望:Minitest 集成现在与 Minitest 5.6+ 兼容

虽然 rspec-expectations 通常与 rspec-core 一起使用,但您可以轻松地将其与其他测试框架一起使用。我们提供了与 Minitest 的集成。只需在加载 Minitest 本身之后加载我们的 Minitest 支持即可

require 'rspec/expectations/minitest_integration'

不幸的是,Minitest 5.6 引入了自己的 expect 方法,该方法与我们提供的 expect 方法冲突,并破坏了这种集成。在 rspec-expectations 3.5 中有一个针对此问题的修复程序。

模拟:添加 Minitest 集成

虽然我们长期以来一直在为 rspec-expectations 提供 Minitest 集成,但我们从未为 rspec-mocks 提供过相同级别的简单集成。相反,用户不得不使用我们提供的生命周期钩子将 rspec-mocks 与 Minitest 本身集成。这工作得很好,直到前面提到的 expect 方法被添加到 Minitest 5.6 并破坏了尝试将 rspec-mocks 与 minitest 一起使用的用户的操作。在 rspec-mocks 3.5 中,我们现在为与 Minitest 的使用提供了一流的支持。只需要求我们的集成文件即可

require 'rspec/mocks/minitest_integration'

Rails:对 Rails 5 的支持

这里的主要内容是 RSpec 3.5.0 与 Rails 5 兼容。随着 Rails 5 测试版和候选版本的发布,我们一直在发布 3.5.0 的测试版,以与 Rails 保持同步。由于这是 Rails 的一个主要版本,因此我们使用的某些 API 已经过时。RSpec 并没有进行主要版本发布,因此这只会在一个地方暴露给您,我们的用户:控制器测试。

Rails 5 中,assignsassert_template 是“软弃用”。控制器测试本身没有弃用,在您的规范中添加 :type => :controller 仍然 100% 受支持。通过 Rails 3 和 4,在控制器规范中使用 assigns 既普遍又习惯。由于这是 RSpec 的一个次要版本,因此我们对 SemVer 的承诺意味着我们不会破坏您现有的控制器规范。对于大量使用 assigns 的现有 Rails 应用程序,将 rails-controller-testing 添加到您的 Gemfile 将恢复 assignsassert_template。RSpec 与这个 gem 无缝集成,因此您的控制器规范应该继续工作。

对于新的 Rails 应用程序:我们不建议将 rails-controller-testing gem 添加到您的应用程序中。Rails 团队和 RSpec 核心团队的官方建议是编写 请求规范。请求规范允许您专注于单个控制器操作,但与控制器测试不同的是,它们涉及路由器、中间件堆栈以及机架请求和响应。这为您的测试增加了真实性,并有助于避免控制器规范中常见的许多问题。在 Rails 5 中,请求规范比 Rails 4 中的请求规范或控制器规范快得多,这要归功于 Rails 提交者团队的 Eileen Uchitelle[^foot_1] 的工作。

我们想讨论的 Rails 5 的另一个重要功能是 ActionCable。不幸的是,RSpec 目前无法提供一种干净的方法来测试 ActionCable。Rails 正在为 ActionCable 开发一种测试类型,计划作为 Rails 5.1 的一部分发布。我们将密切关注它,并在它准备好时开发出解决方案。在此期间,我们建议您通过浏览器以集成的方式测试 ActionCable。

对 Rails 5 的工作代表了 RSpec 核心团队成员的大量投资,并且我们得到了 Rails 提交者和核心团队成员的很大帮助。我们衷心感谢所有参与使这成为可能的人。

统计数据

组合

rspec-core

rspec-expectations

rspec-mocks

rspec-rails

rspec-support

文档

API 文档

Cucumber 特性

发布说明

RSpec Core(合并所有 RSpec 3.5.0 的 Beta 版本)

3.5.0 / 2016-07-01

完整变更日志

增强功能

错误修复

3.5.0.beta4 / 2016-06-05

完整变更日志

增强功能

错误修复

3.5.0.beta3 / 2016-04-02

完整变更日志

增强功能

错误修复

3.5.0.beta2 / 2016-03-10

完整变更日志

增强功能

3.5.0.beta1 / 2016-02-06

完整变更日志

增强功能

错误修复

RSpec Expectations(包括所有 RSpec 3.5.0 的 Beta 版本)

3.5.0 / 2016-07-01

完整变更日志

自 beta4 以来没有面向用户的更改

3.5.0.beta4 / 2016-06-05

完整变更日志

错误修复

3.5.0.beta3 / 2016-04-02

完整变更日志

增强功能

3.5.0.beta2 / 2016-03-10

完整变更日志

增强功能

错误修复

3.5.0.beta1 / 2016-02-06

完整变更日志

增强功能

错误修复

RSpec Mocks(包括所有 RSpec 3.5.0 的 Beta 版本)

3.5.0 / 2016-07-01

完整变更日志

增强功能

3.5.0.beta4 / 2016-06-05

完整变更日志

增强功能

3.5.0.beta3 / 2016-04-02

完整变更日志

增强功能

3.5.0.beta2 / 2016-03-10

完整变更日志

增强功能

错误修复

3.5.0.beta1 / 2016-02-06

完整变更日志

错误修复

RSpec Support(包括所有 RSpec 3.5.0 的 Beta 版本)

3.5.0 / 2016-07-01

完整变更日志

自 beat4 以来没有面向用户的更改

3.5.0.beta4 / 2016-06-05

完整变更日志

增强功能:* 改进 MethodSignature 以更好地支持关键字参数。(#250,Rob Smith)。

3.5.0.beta3 / 2016-04-02

完整变更日志

错误修复

3.5.0.beta2 / 2016-03-10

完整变更日志

没有面向用户的更改。

3.5.0.beta1 / 2016-02-06

完整变更日志

脚注

[^foot_1]: 另请参阅 Eileen 关于请求规范性能的 演讲