由于我面临一些问题,我决定检查before
和after
钩子执行的顺序。我是这样做的:
require "spec_helper"
describe "The order:" do
before(:all) {
puts "before_all"
}
after(:all) {
puts "after_all"
}
before(:each) {
puts "before_each"
}
after(:each) {
puts "after_each"
}
describe "DESC A" do
before {
puts "A_before"
}
it "A_it_1" do
expect(1).to eq(1)
end
it "A_it_2" do
expect(1).to eq(1)
end
end
describe "DESC B" do
before {
puts "B_before"
}
it "B_it_1" do
expect(1).to eq(1)
end
it "B_it_2" do
expect(1).to eq(1)
end
end
end
和我得到的:
The order:
before_all
DESC A
before_each
A_before
after_each
A_it_1
before_each
A_before
after_each
A_it_2
DESC B
before_each
B_before
after_each
B_it_1
before_each
B_before
after_each
B_it_2
after_all
这是怎么回事??after_each
为什么在A_it_1
之前运行
更新:
添加around(:each)
更有趣:
around(:each) do |example|
puts "around_in"
example.run
puts "around_out"
end
和结果:
The order:
before_all
DESC A
around_in
before_each
A_before
after_each
around_out
A_it_1
around_in
before_each
A_before
after_each
around_out
A_it_2
DESC B
around_in
before_each
B_before
after_each
around_out
B_it_1
around_in
before_each
B_before
after_each
around_out
B_it_2
after_all
您的输出和relishapp.com上记录的官方输出都是正确的。发生的事情是,rspec需要在每个示例之后运行after(:each),因为after(:each)中的异常会导致示例失败。在rspec可以在输出中显示示例之前,它需要知道它是绿色还是红色,这意味着在示例的描述出现在输出中之前需要运行after(:each)。
但是,如果您在实际示例中放置一个puts语句,您将看到在它之前出现了before(:each),然后运行示例代码(包括puts),然后是after(:each),正如您所期望的那样,最后,示例的描述输出到屏幕。
像你一样,我也很困惑,直到我意识到rspec打印出示例的标签与它实际做的事情不一致——标签只有在(:all)s之前,(:each)es之前和(:each)es之后为示例运行一次。
注意:after(:all)会在打印出示例标签后运行,因为它们不会影响测试的结果(在after(:all)钩子中会生成一个异常警告,但这不会使测试变为红色)。
RSpec的before
和after
钩子的文档指定了它们运行的顺序。然而,RSpec的around
钩子的文档并没有指定它们运行的顺序。
该规范测试around
、before
和after
、:all
和:each
以及示例的执行顺序。当我使用rspec(-core) 2.14.8运行它时,它们按照您期望的顺序执行:
describe "order in which rspec around/before/after hooks run" do
before :all do
defined?($previous_hook).should be_false # this hook runs first
$previous_hook = "before :all"
end
around :each do |example|
$previous_hook.should == "before :all"
$previous_hook = "around :each 1"
example.run
$previous_hook.should == "after :each"
$previous_hook = "around :each 2"
end
before :each do
$previous_hook.should == "around :each 1"
$previous_hook = "before :each"
end
it "should not raise an exception or print anything" do
$previous_hook.should == "before :each"
$previous_hook = "example"
end
after :each do
$previous_hook.should == "example"
$previous_hook = "after :each"
end
after :all do
# rspec ignores assertion failures and any other exceptions raised here, so all we can do is puts.
# $previous_hook is a global because if it's an instance variable it is "before :all" at this point.
warn "Previous hook was #{$previous_hook}, NOT around :each 2 as expected" unless $previous_hook == "around :each 2"
end
end
注意一些可能令人惊讶的事情:
-
self
在:all
和:each
块中是不同的,所以我需要使用全局变量而不是实例变量。 -
after :all
(但不包括before :all
)吃异常。 - 看看
.should
工作的所有地方!你通常不会想在那里使用它。
这个问题上面已经有了答案,但是要添加一个简单的答案方法。
要查看钩子运行的顺序,您必须在"it"中添加"puts"语句,
describe "The order:" do
before(:all) {
puts "before_all"
}
after(:all) {
puts "after_all"
}
before(:each) {
puts "before_each"
}
after(:each) {
puts "after_each"
}
describe "DESC A" do
before {
puts "A_before"
}
it "A_it_1" do
# expect(1).to eq(1) <<<<---- Change Here
puts "Inside the test"
end
end
end