RSpec - 钩子

当您编写单元测试时,在测试之前和之后运行设置和拆卸代码通常很方便。 设置代码是配置或"设置"测试条件的代码。 拆卸代码进行清理,确保后续测试的环境处于一致的状态。

一般来说,您的测试应该彼此独立。 当您运行一整套测试并且其中一个测试失败时,您希望确信它失败是因为正在测试的代码存在错误,而不是因为之前的测试使环境处于不一致的状态。

RSpec 中最常用的钩子是 before 和 after 钩子。 它们提供了一种定义和运行我们上面讨论的设置和拆卸代码的方法。 让我们考虑一下这个示例代码 −

class SimpleClass 
   attr_accessor :message 
   
   def initialize() 
      puts "\nCreating a new instance of the SimpleClass class" 
      @message = 'howdy' 
   end 
   
   def update_message(new_message) 
      @message = new_message 
   end 
end 

describe SimpleClass do 
   before(:each) do 
      @simple_class = SimpleClass.new 
   end 
   
   it 'should have an initial message' do 
      expect(@simple_class).to_not be_nil
      @simple_class.message = 'Something else. . .' 
   end 
   
   it 'should be able to change its message' do
      @simple_class.update_message('a new message')
      expect(@simple_class.message).to_not be 'howdy' 
   end
end

当您运行此代码时,您将得到以下输出 −

Creating a new instance of the SimpleClass class 
. 
Creating a new instance of the SimpleClass class 
. 
Finished in 0.003 seconds (files took 0.11401 seconds to load) 
2 examples, 0 failures

让我们仔细看看发生了什么。 before(:each) 方法是我们定义设置代码的地方。 当您传递 :each 参数时,您将指示 before 方法在示例组中的每个示例之前运行,即上面代码中的描述块内的两个 it 块。

在 @simple_class = SimpleClass.new 行中,我们创建了 SimpleClass 类的新实例并将其分配给对象的实例变量。 您可能想知道什么对象? RSpec 在描述块的范围内在幕后创建一个特殊的类。 这允许您为此类的实例变量分配值,您可以在示例中的 it 块中访问这些实例变量。 这也使得我们可以轻松地在测试中编写更清晰的代码。 如果每个测试(示例)都需要 SimpleClass 的实例,我们可以将该代码放在 before 挂钩中,而不必将其添加到每个示例中。

请注意,"创建 SimpleClass 类的新实例"行被写入控制台两次,这表明在每个 it 块 中调用钩子之前。

正如我们所提到的,RSpec 还有一个 after 钩子,并且 before 和 after 钩子都可以将:all 作为参数。 after 挂钩将在指定目标之后运行。 : all 目标意味着该钩子将在所有示例之前/之后运行。 这是一个简单的示例,说明了何时调用每个钩子。

describe "Before and after hooks" do 
   before(:each) do 
      puts "Runs before each Example" 
   end 
   
   after(:each) do 
      puts "Runs after each Example" 
   end 
   
   before(:all) do 
      puts "Runs before all Examples" 
   end 
   
   after(:all) do 
      puts "Runs after all Examples"
   end 
   
   it 'is the first Example in this spec file' do 
      puts 'Running the first Example' 
   end 
   
   it 'is the second Example in this spec file' do 
      puts 'Running the second Example' 
   end 
end

当您运行上面的代码时,您将看到以下输出 −

Runs before all Examples 
Runs before each Example 
Running the first Example 
Runs after each Example 
.Runs before each Example 
Running the second Example 
Runs after each Example 
.Runs after all Examples