7种运行特定RSpec测试的方法

339 阅读5分钟

在一个项目中运行测试的最常见方法是在终端运行rspec 。这将运行项目中所有例子的测试。有时,这并不是我们想要的。

在开发过程中,我们不希望每次改变后都要运行整个测试套件。我们大多数人只想运行与我们所做的改变有关的测试以节省时间。

我们可以通过以下方式运行特定的RSpec测试:

1.文件和目录名

通过文件或目录名运行测试是使用RSpec运行测试最熟悉的方式。RSpec可以取一个文件名或目录名并运行该文件或目录的内容。所以你可以这样做。

rspec spec/jobs 运行在job目录中找到的测试。

rspec spec/jobs spec/services 只运行 jobs 和 services 目录中的测试。

rspec spec/models/user_spec.rb 运行 文件中的测试。user_spec.rb

rspec spec/jobs spec/models/user_spec.rb 运行 文件夹中的所有测试,以及 文件中的规格。jobs user_spec.rb

2.示例组的各个部分

从现在开始,让我们使用下面的规格文件和类作为我们的测试样本:

# person_spec.rb

class Person
  attr_accessor :first_name, :last_name, :height, :eye_colour

  def initialize(first_name, last_name, height = 160, eye_colour = 'grey')
    @first_name = first_name
    @last_name = last_name
    @height = height
    @eye_colour = eye_colour
  end

  def local_greeting(greeting)
    greeting.to_s
  end
end

RSpec.describe 'Person' do
  before do
    @person = Person.new('Emmanuel', 'Hayford')
  end

  context 'identity' do
    it 'should tell first name' do
      expect(@person.first_name).to eq('Emmanuel')
    end

    it 'should tell last name' do
      expect(@person.last_name).to eq('Hayford')
    end
  end

  context 'physical features' do
    it 'should be able to tell height' do
      expect(@person.height).to eq(160)
    end

    it 'should be able to tell eye colour' do
      expect(@person.eye_colour).to eq('grey')
    end
  end

  context 'culture' do
    it 'should be able to greet in local language' do
      local_greeting = @person.local_greeting('Maakye')

      expect(local_greeting).to eq('Maakye')
    end
  end
end

RSpec允许在一个示例组中选择一个(或几个)部分来运行,允许我们运行类似rspec person_spec.rb:21 ,其中21 是我们想要运行的部分的行号。该行号可以落在这些RSpec方法中的任何一个。describe,context,itexpect ,RSpec将运行该部分。如果该行落在一个空行上,RSpec将运行测试文件中最接近的(从顶部开始)it 块。如果空行在所有测试例子的上方,RSpec将运行所有的测试。

我们也可以通过做rspec person_spec.rb[1:3] 来运行一个测试部分。[x:y] 格式指示RSpec运行x组(在我们的例子中,我们只有一个组...也就是RSpec.describe 'Person' 块内的所有内容)和y例子块。因此,运行rspec person_spec.rb[1:3] 将运行'culture' 块。你可以做多个部分,比如rspec person_spec.rb[1:1,1:3] ,它将只运行'identity''culture' 块。

3.一个例子的描述

你可以像这样运行一个测试:rspec person_spec.rb -e "greet" ;这将运行所有描述中带有 "greet "的例子/组-e 标志是--example 的简称。值得注意的是,这是区分大小写的,所以rspec person_spec.rb -e "greet"rspec person_spec.rb -e "Greet" 不会产生相同的结果。

在我们的规范文件中运行rspec person_spec.rb -e "greet" -fd ,将返回:

Run options: include {:full_description=>/greet/}

Person
  culture
    should be able to greet in local language

Finished in 0.00088 seconds (files took 0.09423 seconds to load)
1 example, 0 failures

只有一个例子的描述中含有 "greet"。

4.聚焦在一个例子上

如果你只做一个测试或正在做的一组测试,这个功能就很方便。为了使用这个功能,你必须在配置上多走一步。所谓的配置就是:

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

在一个典型的Rails项目中,这可能在你的spec_helper.rb 文件中。一旦这个配置到位,你可以把f 添加到describecontextit ,这样它就变成了fdescribefcontextfit ,RSpec就会 "关注 "这个例子/组。做到这一点:

fit 'should tell height' do
  expect(@person.height).to eq(160)
end

相当于

it 'should tell height', focus: true do
  expect(@person.height).to eq(160)
end

5.只运行失败的测试

RSpec有rspec file_name_spec.rb --only-failures ,当你只对运行失败的测试感兴趣时非常方便,这样你就可以致力于修复它们。但是为了跟踪上次运行测试时哪些测试失败了,RSpec需要另一个配置,告诉它在哪里存储哪些测试失败/通过的信息。

这个配置应该是这样的

RSpec.configure do |config|
  config.example_status_persistence_file_path = 'some_file.txt'
end

如果你使用的是Git,你可能想把some_file.txt 添加到.gitignore

在没有任何标志的情况下运行一次这个文件,以记录所有例子的状态,这是我们第一次运行测试后的内容,其中有一些(故意的)失败的例子,这一点很重要。

一旦第一次运行记录了测试的状态,我们就可以运行rspec person_spec.rb --only-failures ,只运行失败的测试,并在我们对代码进行修改后重新运行,看看我们是否已经能够修复我们正在跟踪的失败,如果是,它的状态将在我们为RSpec配置的文件中变为 "通过",以进行跟踪。

6.运行失败的测试(一次性的)

如果有多个失败,rspec person_spec.rb --only-failures ,你可以做rspec person_spec.rb --next-failure ,每次重复运行一个失败。很好!

7.标签过滤

你可以用哈希值(RSpec称之为 "元数据",你在上面看到的测试中的focus: true 就是一个元数据例子)来标记例子/组。哈希值可以包含你选择的任意键/值。例如,让我们说我们想把一些测试标记为重要。我们可以通过改变我们的测试,添加一个important: true ,使其看起来像下面这样:

RSpec.describe 'Person' do
  before do
    @person = Person.new('Emmanuel', 'Hayford')
  end

  context 'identity', important: true do # 👈
    it 'should tell first name' do
      expect(@person.first_name).to eq('Emmanuel')
    end

    it 'should tell last name'  do
      expect(@person.last_name).to eq('Hayford')
    end
  end

  context 'physical features', important: false do # 👈
    it 'should be able to tell height' do
      expect(@person.height).to eq(160)
    end

    it 'should be able to tell eye colour' do
      expect(@person.eye_colour).to eq('grey')
    end
  end

  context 'culture', important: true do # 👈
    it 'should be able to greet in local language' do
      local_greeting = @person.local_greeting('Maakye')

      expect(local_greeting).to eq('Maakye')
    end
  end
end

有了这个改变,我们可以运行rspec person_spec.rb --tag important ,并期望只有3个例子在运行,而不是5个:

Run options: include {:important=>true}
...

Finished in 0.00721 seconds (files took 0.09502 seconds to load)
3 examples, 0 failures

有了这些,我相信我们可以节省大量的时间,这些时间我们可以投入到做其他事情上。挑选你想要的测试会加快开发速度。我建议用实际工作来做这件事。