在一个项目中运行测试的最常见方法是在终端运行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,it 或expect ,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 添加到describe 、context 或it ,这样它就变成了fdescribe 、fcontext 或fit ,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
有了这些,我相信我们可以节省大量的时间,这些时间我们可以投入到做其他事情上。挑选你想要的测试会加快开发速度。我建议用实际工作来做这件事。