特征测试 rake 任务将输出添加到标准输出。如何避免这种情况?

Feature testing rake tasks adds up the output to stdout. How to avoid this?

我尝试对 Rake 任务进行功能测试并捕获其输出:

这是一个完整的集成测试(功能测试),它 意味着我想端到端地测试它。所以我对存根不感兴趣 出一些 ConsoleRenderer class,只是测试当我 运行 任务时,我 在 stdout.

中查看某些输出

大大简化的实现是

namespace :output do
  task :world do
    print 'hello world'
  end

  task :mars do
    print 'hello mars'
  end
end

以及功能测试(rspec 3.3):

require 'feature_helper'

describe 'some output' do
  before do
    Rails.application.load_tasks
  end

  after do
    Rake::Task['output:world'].reenable
    Rake::Task['output:mars'].reenable
  end

  it 'outputs' do
    expect { Rake::Task['output:world'].invoke }.to output('hello world').to_stdout
  end

  it 'outputs again' do
    expect { Rake::Task['output:world'].invoke }.to output('hello world').to_stdout
  end

  it 'outputs mars' do
    expect { Rake::Task['output:mars'].invoke }.to output('hello mars').to_stdout
  end
end

当 运行 这样做时,过去 运行 的输出以某种方式加起来:

$ bundle exec rspec spec/features/output_spec.rb --order defined
.FF

Failures:

  1) some output outputs again
     Failure/Error: expect { Rake::Task['output:world'].invoke }.to output('hello world').to_stdout
       expected block to output "hello world" to stdout, but output "hello worldhello world"
     # ./spec/features/output_spec.rb:18:in `block (2 levels) in <top (required)>'

  2) some output outputs mars
     Failure/Error: expect { Rake::Task['output:mars'].invoke }.to output('hello mars').to_stdout
       expected block to output "hello mars" to stdout, but output "hello marshello marshello mars"
     # ./spec/features/output_spec.rb:22:in `block (2 levels) in <top (required)>'

为了说明,我运行按定义顺序测试。 第一个测试通过。第二个失败了,因为它以某种方式包含了 之前测试中 $stdout 的输出,或者 运行s 本身的两次输出。第三个也是如此(它本身似乎 运行 三次)。

我怀疑这是 Rake 任务中的问题,因为当我简化 测试只是 print 的东西,这个添加不会发生:

it 'outputs' do
  expect { print 'hello world' }.to output('hello world').to_stdout
end

it 'outputs again' do
  expect { print 'hello world' }.to output('hello world').to_stdout
end

it 'outputs mars' do
  expect { print 'hello mars' }.to output('hello mars').to_stdout
end

这个通过就好了。

请注意,在控制台上 运行ning

Rake::Task['output:mars'].invoke
Rake::Task['output:mars'].reenable
Rake::Task['output:mars'].invoke

一次输出"hello mars",然后再次输出"hello mars"。问题不 在这样的环境中自我繁殖。

我需要重置、重新启用、重新导入什么,t运行cate 或其他 更改,以便输出不相加?

原来调用 reenable 不正确。相反,我应该使用 clear。它自己的文档是 "Normally used in the unit tests.".

after do
  Rake.application.clear
end

注意: 这修复了它,但我仍然不知道为什么或者问题中描述的设置在某个时候运行任务三次。因此,解释 why 行为的答案是这样的,而 why 运行 clear 没有那个,将优先于我自己的回答。

之所以执行了两次或三次,是因为你在每个块之前加载了任务:

before do
  Rails.application.load_tasks
end

改为使用before :all 并可选择在加载前使用 Rails.application.clear,因为如果您在另一个规范中加载任务,它们仍然会存在