beforeafter钩子

使用beforeafter钩子在运行示例主体之前和/或之后执行任意代码

  before(:example) # run before each example
  before(:context) # run one time only, before all of the examples in a group

  after(:example) # run after each example
  after(:context) # run one time only, after all of the examples in a group

beforeafter块按以下顺序调用

  before :suite
  before :context
  before :example
  after  :example
  after  :context
  after  :suite

一个裸beforeafter钩子默认为:example范围。

beforeafter钩子可以在它们应该运行的示例组中直接定义,也可以在全局RSpec.configure块中定义。注意,示例的状态不会影响钩子。

警告:before(:suite)中不支持设置实例变量。

警告:模拟仅在before(:example)中受支持。

警告:around钩子将在任何before钩子之前执行,并在任何after钩子之后执行,而无论它们在哪个上下文中定义。

注意::example:context范围也分别可用作:each:all。使用您喜欢的任何一个。

定义before(:example)

给定一个名为“before_example_spec.rb”的文件,其中包含

require "rspec/expectations"

class Thing
  def widgets
    @widgets ||= []
  end
end

RSpec.describe Thing do
  before(:example) do
    @thing = Thing.new
  end

  describe "initialized in before(:example)" do
    it "has 0 widgets" do
      expect(@thing.widgets.count).to eq(0)
    end

    it "can accept new widgets" do
      @thing.widgets << Object.new
    end

    it "does not share state across examples" do
      expect(@thing.widgets.count).to eq(0)
    end
  end
end

我运行rspec before_example_spec.rb

那么所有示例都应该通过。

在示例组中定义before(:context)

给定一个名为“before_context_spec.rb”的文件,其中包含

require "rspec/expectations"

class Thing
  def widgets
    @widgets ||= []
  end
end

RSpec.describe Thing do
  before(:context) do
    @thing = Thing.new
  end

  describe "initialized in before(:context)" do
    it "has 0 widgets" do
      expect(@thing.widgets.count).to eq(0)
    end

    it "can accept new widgets" do
      @thing.widgets << Object.new
    end

    it "shares state across examples" do
      expect(@thing.widgets.count).to eq(1)
    end
  end
end

我运行rspec before_context_spec.rb

那么所有示例都应该通过

我运行rspec before_context_spec.rb:15

那么所有示例都应该通过。

before(:context)块中的失败

给定一个名为“before_context_spec.rb”的文件,其中包含

RSpec.describe "an error in before(:context)" do
  before(:context) do
    raise "oops"
  end

  it "fails this example" do
  end

  it "fails this example, too" do
  end

  after(:context) do
    puts "after context ran"
  end

  describe "nested group" do
    it "fails this third example" do
    end

    it "fails this fourth example" do
    end

    describe "yet another level deep" do
      it "fails this last example" do
      end
    end
  end
end

我运行rspec before_context_spec.rb --format documentation

那么输出应该包含“5 个示例,5 个失败”

并且输出应该包含

an error in before(:context)
  fails this example (FAILED - 1)
  fails this example, too (FAILED - 2)
  nested group
    fails this third example (FAILED - 3)
    fails this fourth example (FAILED - 4)
    yet another level deep
      fails this last example (FAILED - 5)
after context ran

我运行rspec before_context_spec.rb:9 --format documentation

那么输出应该包含“1 个示例,1 个失败”

并且输出应该包含

an error in before(:context)
  fails this example, too (FAILED - 1)

after(:context)块中的失败

给定一个名为“after_context_spec.rb”的文件,其中包含

RSpec.describe "an error in after(:context)" do
  after(:context) do
    raise StandardError.new("Boom!")
  end

  it "passes this example" do
  end

  it "passes this example, too" do
  end
end

我运行rspec after_context_spec.rb

那么它应该失败,并显示

An error occurred in an `after(:context)` hook.
Failure/Error: raise StandardError.new("Boom!")

StandardError:
  Boom!
# ./after_context_spec.rb:3

示例中的失败不会影响钩子

给定一个名为“failure_in_example_spec.rb”的文件,其中包含

RSpec.describe "a failing example does not affect hooks" do
  before(:context) { puts "before context runs" }
  before(:example) { puts "before example runs" }
  after(:example) { puts "after example runs" }
  after(:context) { puts "after context runs" }

  it "fails the example but runs the hooks" do
    raise "An Error"
  end
end

我运行rspec failure_in_example_spec.rb

那么它应该失败,并显示

before context runs
before example runs
after example runs
Fafter context runs

在配置中定义beforeafter

给定一个名为“befores_in_configuration_spec.rb”的文件,其中包含

require "rspec/expectations"

RSpec.configure do |config|
  config.before(:example) do
    @before_example = "before example"
  end
  config.before(:context) do
    @before_context = "before context"
  end
end

RSpec.describe "stuff in before blocks" do
  describe "with :context" do
    it "should be available in the example" do
      expect(@before_context).to eq("before context")
    end
  end
  describe "with :example" do
    it "should be available in the example" do
      expect(@before_example).to eq("before example")
    end
  end
end

我运行rspec befores_in_configuration_spec.rb

那么所有示例都应该通过。

before/after块按顺序运行

给定一个名为“ensure_block_order_spec.rb”的文件,其中包含

require "rspec/expectations"

RSpec.describe "before and after callbacks" do
  before(:context) do
    puts "before context"
  end

  before(:example) do
    puts "before example"
  end

  before do
    puts "also before example but by default"
  end

  after(:example) do
    puts "after example"
  end

  after do
    puts "also after example but by default"
  end

  after(:context) do
    puts "after context"
  end

  it "gets run in order" do

  end
end

我运行rspec --format progress ensure_block_order_spec.rb

那么输出应该包含

before context
before example
also before example but by default
also after example but by default
after example
.after context

在配置中定义的before/after块按顺序运行

给定一个名为“configuration_spec.rb”的文件,其中包含

require "rspec/expectations"

RSpec.configure do |config|
  config.before(:suite) do
    puts "before suite"
  end

  config.before(:context) do
    puts "before context"
  end

  config.before(:example) do
    puts "before example"
  end

  config.after(:example) do
    puts "after example"
  end

  config.after(:context) do
    puts "after context"
  end

  config.after(:suite) do
    puts "after suite"
  end
end

RSpec.describe "ignore" do
  example "ignore" do
  end
end

我运行rspec --format progress configuration_spec.rb

那么输出应该包含

before suite
before context
before example
after example
.after context
after suite

before/after上下文块运行一次

给定一个名为“before_and_after_context_spec.rb”的文件,其中包含

RSpec.describe "before and after callbacks" do
  before(:context) do
    puts "outer before context"
  end

  example "in outer group" do
  end

  after(:context) do
    puts "outer after context"
  end

  describe "nested group" do
    before(:context) do
      puts "inner before context"
    end

    example "in nested group" do
    end

    after(:context) do
      puts "inner after context"
    end
  end

end

我运行rspec --format progress before_and_after_context_spec.rb

那么所有示例都应该通过

并且输出应该包含

outer before context
.inner before context
.inner after context
outer after context

我运行rspec --format progress before_and_after_context_spec.rb:14

那么所有示例都应该通过

并且输出应该包含

outer before context
inner before context
.inner after context
outer after context

我运行rspec --format progress before_and_after_context_spec.rb:6

那么所有示例都应该通过

并且输出应该包含

outer before context
.outer after context

嵌套示例可以访问在外部before(:context)中设置的状态

给定一个名为“before_context_spec.rb”的文件,其中包含

RSpec.describe "something" do
  before :context do
    @value = 123
  end

  describe "nested" do
    it "access state set in before(:context)" do
      expect(@value).to eq(123)
    end

    describe "nested more deeply" do
      it "access state set in before(:context)" do
        expect(@value).to eq(123)
      end
    end
  end

  describe "nested in parallel" do
    it "access state set in before(:context)" do
      expect(@value).to eq(123)
    end
  end
end

我运行rspec before_context_spec.rb

那么所有示例都应该通过。

before/after上下文块可以访问状态

给定一个名为“before_and_after_context_spec.rb”的文件,其中包含

RSpec.describe "before and after callbacks" do
  before(:context) do
    @outer_state = "set in outer before context"
  end

  example "in outer group" do
    expect(@outer_state).to eq("set in outer before context")
  end

  describe "nested group" do
    before(:context) do
      @inner_state = "set in inner before context"
    end

    example "in nested group" do
      expect(@outer_state).to eq("set in outer before context")
      expect(@inner_state).to eq("set in inner before context")
    end

    after(:context) do
      expect(@inner_state).to eq("set in inner before context")
    end
  end

  after(:context) do
    expect(@outer_state).to eq("set in outer before context")
  end
end

我运行rspec before_and_after_context_spec.rb

那么所有示例都应该通过。

before(:example)中的异常被捕获并作为失败报告

给定一个名为“error_in_before_example_spec.rb”的文件,其中包含

RSpec.describe "error in before(:example)" do
  before(:example) do
    raise "this error"
  end

  it "is reported as failure" do
  end
end

我运行rspec error_in_before_example_spec.rb

那么输出应该包含“1 个示例,1 个失败”

并且输出应该包含“此错误”。