- en
- ja
RSpec 3.4 已经发布了!
Myron Marston
2015 年 11 月 13 日RSpec 3.4 刚刚发布!鉴于我们对 语义版本控制 的承诺,对于已经使用任何 RSpec 3 版本的用户来说,这应该是一个微不足道的升级。但是,如果我们引入了任何回归问题,请告诉我们,我们会尽快发布一个包含修复的补丁版本。
RSpec 继续是一个社区驱动的项目,来自世界各地的贡献者参与其中。此版本包含来自近 50 位不同贡献者的 500 多个提交和 160 个合并的拉取请求!
感谢所有帮助完成此版本发布的人!
值得注意的变更
核心:二分查找算法改进
RSpec 3.3 发布了一个新的 --bisect
选项,用于在追踪排序依赖来源时识别最小的重现命令。核心二分查找算法使用了一种朴素的排列方法:在每一轮中,它首先尝试一半的示例,然后尝试另一半,然后尝试一半示例的每种组合,直到找到可以安全忽略的一半。这通常效果不错,但有一些糟糕的最坏情况行为。特别是,如果你的排序依赖中涉及多个罪魁祸首,则可能需要很多次组合才能命中包含两个罪魁祸首的组合。同样,如果算法已经到达了一半以上剩余示例是罪魁祸首的点,它将穷尽地尝试每种组合,直到不再剩下任何示例——这将花费很长时间。
在 RSpec 3.4 中,二分查找算法更智能。它现在使用一种递归方法,旨在最大程度地减少识别罪魁祸首所需的尝试次数。对新算法的早期反馈非常积极:Sam Livingston-Gray 报告说,3.3 二分查找运行了一整晚都没有完成,但使用新算法,它只在 20 分钟内就完成了!
感谢 Simon Coffey 的实现!如果你想了解更多信息,我建议你 查看他的 PR——它包含一些非常有用的图表,解释了新算法的工作原理。
核心:失败输出改进
良好的失败输出一直是 RSpec 的优先事项,但在 3.4 中它得到了很大的改进,并且在以下几个方面有所改进
多行代码片段
RSpec 在失败输出中包含来自预期失败的代码片段。在 RSpec 3.4 之前,只要你的预期适合一行,这通常效果不错。如果你将其格式化为多行,例如这样
expect {
MyNamespace::MyClass.some_long_method_name(:with, :some, :arguments)
}.to raise_error(/some error snippet/)
…那么失败将只打印第一行(expect {
),因为这是异常中包含的堆栈帧。在 RSpec 3.4 中,我们现在会从标准库加载 Ripper(如果它在标准库中可用),以解析源代码并确定要包含用于完整预期表达式的行数。对于像上面的片段这样的情况,失败输出现在将包含整个表达式。
还有一个新的配置选项可以与之搭配:config.max_displayed_failure_line_count
,它默认为 10,并设置了片段大小的限制。
感谢 Yuji Nakayama 的 实现!
安装 coderay
以进行语法高亮
更进一步,如果 coderay
gem 可用,RSpec 3.4 将使用它在你的终端中对代码片段进行语法高亮。这是一个使用上面的代码片段的示例
更好的失败源代码检测
RSpec 通过查看异常堆栈跟踪以查找合适的框架来查找失败代码片段。我们只需要使用顶部堆栈帧,但这通常不是你想要的:当你遇到预期失败时,顶部帧引用的是 RSpec 中的一个链接,其中 RSpec::Expectations::ExpectationNotMetError
被抛出,而你想要看到来自你的 expect
调用位置的代码片段,而不是看到 RSpec 代码的片段。在 RSpec 3.4 之前,我们对此的解决方案相当简单:我们只是查找当前运行的示例文件所在规范的第一个堆栈帧。在某些情况下,这将显示错误的代码片段(例如,当你的示例调用在 spec/support
文件中定义的辅助方法时,真正的失败发生在该文件里)。在其他情况下,它什么也找不到,我们最终显示了 无法从回溯中找到匹配的行
而不是它。
RSpec 3.4 具有更好的查找源代码片段的逻辑:现在我们查找来自 config.project_source_dirs
(默认为 lib
、app
和 spec
)的第一个框架,如果找不到匹配的框架,我们将退回到第一个堆栈帧。你应该不会再看到 无法从回溯中找到匹配的行
了!
期望:更好的复合失败消息
继续“改进失败输出”主题,rspec-expectations 3.4 为复合期望提供了更好的失败消息。以前,我们会将每个失败消息组合成一行。例如,此期望
expect(lyrics).to start_with("There must be some kind of way out of here")
.and include("No reason to get excited")
…产生了此难以阅读的失败
1) All Along the Watchtower has the expected lyrics
Failure/Error: expect(lyrics).to start_with("There must be some kind of way out of here")
expected "I stand up next to a mountain And I chop it down with the edge of my hand" to start with "There must be some kind of way out of here" and expected "I stand up next to a mountain And I chop it down with the edge of my hand" to include "No reason to get excited"
# ./spec/example_spec.rb:20:in `block (2 levels) in <top (required)>'
在 RSpec 3.4 中,我们对每个单独的失败消息进行格式化,使其更易于阅读
1) All Along the Watchtower has the expected lyrics
Failure/Error:
expect(lyrics).to start_with("There must be some kind of way out of here")
.and include("No reason to get excited")
expected "I stand up next to a mountain And I chop it down with the edge of my hand" to start with "There must be some kind of way out of here"
...and:
expected "I stand up next to a mountain And I chop it down with the edge of my hand" to include "No reason to get excited"
# ./spec/example_spec.rb:20:in `block (2 levels) in <top (required)>'
期望:向 match
匹配器添加 with_captures
在 RSpec 3.4 中,match
匹配器获得了一种新功能:你可以指定正则表达式捕获。你可以使用新的 with_captures
方法来指定有序捕获
year_regex = /(\d{4})\-(\d{2})\-(\d{2})/
expect(year_regex).to match("2015-12-25").with_captures("2015", "12", "25")
…或者指定命名捕获
year_regex = /(?<year>\d{4})\-(?<month>\d{2})\-(?<day>\d{2})/
expect(year_regex).to match("2015-12-25").with_captures(
year: "2015",
month: "12",
day: "25"
)
感谢 Sam Phippen 和 Jason Karns 共同开发此新功能。
Rails:针对 ActiveJob 的新 have_enqueued_job
匹配器
Rails 4.2 发布了 ActiveJob,rspec-rails 3.4 现在有一个匹配器,允许你指定一段代码会将一个作业排队。它支持一个流利的接口,如果你是一个 rspec-mocks 用户,你会发现它很熟悉
expect {
HeavyLiftingJob.perform_later
}.to have_enqueued_job
expect {
HelloJob.perform_later
HeavyLiftingJob.perform_later
}.to have_enqueued_job(HelloJob).exactly(:once)
expect {
HelloJob.perform_later
HelloJob.perform_later
HelloJob.perform_later
}.to have_enqueued_job(HelloJob).at_least(2).times
expect {
HelloJob.perform_later
}.to have_enqueued_job(HelloJob).at_most(:twice)
expect {
HelloJob.perform_later
HeavyLiftingJob.perform_later
}.to have_enqueued_job(HelloJob).and have_enqueued_job(HeavyLiftingJob)
expect {
HelloJob.set(wait_until: Date.tomorrow.noon, queue: "low").perform_later(42)
}.to have_enqueued_job.with(42).on_queue("low").at(Date.tomorrow.noon)
感谢 Wojciech Wnętrzak 实现此功能!
统计
组合
- 总提交数: 502
- 合并的拉取请求: 163
- 48 位贡献者:Aaron Kromer、Alex Dowad、Alex Egan、Alex Pounds、Andrew Horner、Ara Hacopian、Ashley Engelund (aenw / weedySeaDragon)、Ben Woosley、Bradley Schaefer、Brian John、Bryce McDonnell、Chris Zetter、Dan Kohn、Dave Marr、Dennis Günnewig、Diego Carrion、Edward Park、Gavin Miller、Jack Scotti、Jam Black、Jamela Black、Jason Karns、Jon Moss、Jon Rowe、Leo Cassarani、Liz Rush、Marek Tuchowski、Max Meyer、Myron Marston、Nikki Murray、Pavel Pravosud、Sam Phippen、Sebastián Tello、Simon Coffey、Tim Mertens、Wojciech Wnętrzak、Xavier Shay、Yuji Nakayama、Zshawn Syed、bennacer860、bootstraponline、draffensperger、georgeu2000、jackscotti、mrageh、rafik、takiy33、unmanbearpig
rspec-core
- 总提交数: 180
- 合并的拉取请求: 52
- 24 位贡献者:Aaron Kromer、Alex Pounds、Ashley Engelund (aenw / weedySeaDragon)、Ben Woosley、Bradley Schaefer、Brian John、Edward Park、Gavin Miller、Jack Scotti、Jon Moss、Jon Rowe、Leo Cassarani、Marek Tuchowski、Myron Marston、Sebastián Tello、Simon Coffey、Tim Mertens、Yuji Nakayama、bennacer860、bootstraponline、draffensperger、jackscotti、mrageh、takiy33
rspec-expectations
- 总提交数: 93
- 合并的拉取请求: 34
- 17 位贡献者:Aaron Kromer、Alex Egan、Bradley Schaefer、Brian John、Dennis Günnewig、Jason Karns、Jon Moss、Jon Rowe、Max Meyer、Myron Marston、Nikki Murray、Sam Phippen、Xavier Shay、Yuji Nakayama、Zshawn Syed、mrageh、unmanbearpig
rspec-mocks
- 总提交数: 77
- 合并的拉取请求: 26
- 12 位贡献者:Aaron Kromer、Alex Dowad、Alex Egan、Brian John、Bryce McDonnell、Jon Moss、Jon Rowe、Liz Rush、Myron Marston、Pavel Pravosud、Sam Phippen、georgeu2000
rspec-rails
- 总提交数: 97
- 合并的拉取请求: 31
- 16 位贡献者:Aaron Kromer、Alex Egan、Ara Hacopian、Bradley Schaefer、Brian John、Chris Zetter、Dan Kohn、Dave Marr、Diego Carrion、Jam Black、Jamela Black、Jon Moss、Jon Rowe、Myron Marston、Nikki Murray、Wojciech Wnętrzak
rspec-support
- 总提交数: 55
- 合并的拉取请求: 20
- 10 位贡献者:Aaron Kromer、Alex Egan、Andrew Horner、Bradley Schaefer、Brian John、Jon Rowe、Myron Marston、Xavier Shay、Yuji Nakayama、rafik
文档
API 文档
Cucumber 功能
发行说明
rspec-core 3.4.0
增强功能
- 将多个
--pattern
参数组合起来,使其等效于--pattern=1,2,...,n
。 (Jon Rowe, #2002) - 改进
RSpec::Core::Example
对象的inspect
和to_s
输出,替换 Ruby 过于冗长的输出。(Gavin Miller, #1922) - 添加
silence_filter_announcements
配置选项。(David Raffensperger, #2007) - 在报告器协议中添加可选的
example_finished
通知,用于当你不在乎示例结果时。(Jon Rowe, #2013) - 将
--bisect
切换为基于递归的二分查找算法,而不是基于排列的算法。这更好地处理示例依赖于多个其他示例而不是仅仅一个的情况,并最大程度地减少确定示例集无法进一步最小化的运行次数。(Simon Coffey, #1997) - 允许通过真值触发简单的过滤器(例如,只有
:symbol
键)。(Tim Mertens, #2035) - 删除在使用 RSpec 的
--color
选项时,关于在 Windows 上需要ansicon
的不必要警告。(Ashley Engelund, #2038) - 添加选项以配置 RSpec,使其在发出警告时引发错误。(Jon Rowe, #2052)
- 当
cause
可用时,将失败或错误的根cause
附加到打印的失败输出。(Adam Magan) - 停止救援
NoMemoryError
、SignalExcepetion
、Interrupt
和SystemExit
。干扰它们很危险。(Myron Marston, #2063) - 添加
config.project_source_dirs
设置,RSpec 使用它来确定回溯行来自你的项目源代码还是来自某个外部库。它默认为spec
、lib
和app
,但可以配置为不同的值。(Myron Marston, #2088) - 改进失败行检测,以便它在任何项目源代码目录中查找失败行,而不仅仅是在规范文件中。此外,如果找不到来自项目源代码文件的回溯行,我们将退回到显示第一个回溯行的源代码。这应该几乎消除了“无法从回溯中找到匹配的行”消息。(Myron Marston, #2088)
- 添加对
:extra_failure_lines
示例元数据的支持,该元数据将被附加到失败输出。(bootstraponline, #2092)。 - 添加
RSpec::Core::Example#duplicate_with
以使用克隆的元数据生成新的示例。(bootstraponline, #2098) - 添加
RSpec::Core::Configuration#on_example_group_definition
以注册在创建示例组时要调用的钩子。(bootstraponline, #2094) - 向
RSpec::Core::ExampleGroup
添加add_example
和remove_example
以允许操作示例组的示例。(bootstraponline, #2095) - 当 Ripper 可用时(MRI >= 1.9.2 以及 JRuby >= 1.7.5 && < 9.0.0.0.rc1),在失败输出中显示多行失败源代码行。(Yuji Nakayama, #2083)
- 添加
max_displayed_failure_line_count
配置选项(默认为 10)。(Yuji Nakayama, #2083) - 增强
fail_fast
选项,使其可以接受一个数字(例如--fail-fast=3
)以强制在指定数量的失败后中止运行。(Jack Scotti, #2065) - 当
color
启用且coderay
gem 安装在 POSIX 系统上时,在文本格式化程序中对失败代码片段进行语法高亮。(Myron Marston, #2109)
错误修复
- 在从
example_status_persistence_file
读取和写入时锁定它,以防止多个进程尝试使用它时出现竞争条件。(Ben Woosley, #2029) - 修复了 3.3 中导致包含方括号的规范文件名(例如
1[]_spec.rb
)无法正确加载的回归问题。(Myron Marston, #2041) - 修复了 1.9.3 上由 ASCII 文字引起的输出编码问题 (Jon Rowe, #2072)
- 修复了
rspec/core/rake_task.rb
中的需要,以避免一些用户看到的双重需要。(Myron Marston, #2101)
rspec-expectations 3.4.0
增强功能
- 当在 MRI 1.9 上的子类中已经包含了
RSpec::Matchers
后,又在超类中包含它时,将发出警告,因为这种情况会导致使用super
触发无限递归。 (Myron Marston, #816) - 停止救援
NoMemoryError
、SignalExcepetion
、Interrupt
和SystemExit
。干预这些操作很危险。 (Myron Marston, #845) - 在 match 匹配器 中添加
#with_captures
,允许用户在将正则表达式与字符串匹配时指定预期的捕获。 (Sam Phippen, #848) - 始终以多行形式打印复合失败消息。试图将所有内容都打印在一行上,读起来不太好。 (Myron Marston, #859)
错误修复
- 修复动态谓词匹配器在对象不响应谓词时的失败消息,以便对它进行检查而不是依赖于它的
to_s
- 这样,对于nil
,将打印"nil"
而不是空字符串。 (Myron Marston, #841) - 修复在对
#each
包含自身对象的 Enumerable 对象进行差异化时引发的 SystemStackError。 (Yuji Nakayama, #857)
rspec-mocks 3.4.0
增强功能
- 使
expect(...).to have_received
在不依赖 rspec-expectations 的情况下也能工作。 (Myron Marston, #978) - 添加选项,当对
nil
设置期望时,使测试失败。 (Liz Rush, #983)
错误修复
- 修复
have_received { ... }
,以便在接收消息时传递的任何块都将转发到have_received
块。 (Myron Marston, #1006) - 修复在对
respond_to?
进行存根时,错误生成器中的无限循环。 (Alex Dowad, #1022) - 修复在 1.8.7 中,在子类(在类级别)上使用
receive
时出现的问题。 (Alex Dowad, #1026)
rspec-rails 3.4.0
增强功能
- 改进了
have_rendered
匹配器在重定向响应上的失败消息。 (Alex Egan, #1440) - 添加配置选项以从回溯中过滤掉 Rails gems。 (Bradley Schaefer, #1458)
- 为视图规范启用解析器缓存,以大幅提高速度 (Chris Zetter, #1452)
- 添加
have_enqueued_job
匹配器,用于检查块是否已排队作业。 (Wojciech Wnętrzak, #1464)
错误修复
- 修复另一个加载顺序问题,该问题会导致在加载 rspec-rails 之后创建规范时出现未定义方法
fixture_path
错误。 (Nikki Murray, #1430) - 删除了 rspec-rails 回溯排除模式中针对其自身
lib
代码的错误的周围空格。 (Jam Black, #1439)
rspec-support 3.4.0
增强功能
- 改进基于
Delegator
的对象的格式(例如SimpleDelgator
)在失败消息和差异中的格式。 (Andrew Horner, #215) - 添加
ComparableVersion
。 (Yuji Nakayama, #245) - 添加
Ripper
支持检测。 (Yuji Nakayama, #245)
错误修复
- 解决 JRuby 中的一个 bug,该 bug 报告
attr_writer
方法没有参数,导致 RSpec 的验证双重在 JRuby 上模拟或存根写入方法时错误地失败。 (Myron Marston, #225)