51

コンソールにいくつかのメッセージを表示するクラスをテストしています (puts、p 警告など)。RSpec テスト中にこの出力を抑制する機能があるかどうか疑問に思っています。

4

8 に答える 8

50

テキスト ファイルにputsリダイレクトすることで、クラスの出力を抑制しています。$stoutそうすれば、何らかの理由で出力を表示する必要がある場合でも、出力は表示されますが、テスト結果が混乱することはありません。

#spec_helper.rb
RSpec.configure do |config|
  config.before(:all, &:silence_output)
  config.after(:all,  &:enable_output)
end

public
# Redirects stderr and stout to /dev/null.txt
def silence_output
  # Store the original stderr and stdout in order to restore them later
  @original_stderr = $stderr
  @original_stdout = $stdout

  # Redirect stderr and stdout
  $stderr = File.new(File.join(File.dirname(__FILE__), 'dev', 'null.txt'), 'w')
  $stdout = File.new(File.join(File.dirname(__FILE__), 'dev', 'null.txt'), 'w')
end

# Replace stderr and stdout so anything else is output correctly
def enable_output
  $stderr = @original_stderr
  $stdout = @original_stdout
  @original_stderr = nil
  @original_stdout = nil
end

編集:

@MyronMarston のコメントに応えて、メソッドをブロックとして直接挿入する方がおそらく賢明でしょbeforeafter

#spec_helper.rb
RSpec.configure do |config|
  original_stderr = $stderr
  original_stdout = $stdout
  config.before(:all) do 
    # Redirect stderr and stdout
    $stderr = File.new(File.join(File.dirname(__FILE__), 'dev', 'null.txt'), 'w')
    $stdout = File.new(File.join(File.dirname(__FILE__), 'dev', 'null.txt'), 'w')
  end
  config.after(:all) do 
    $stderr = original_stderr
    $stdout = original_stdout
  end
end

それは少しきれいに見え、メソッドをmain. また、Ruby 2.0 を使用している場合は、__dir__代わりにFile.dirname(__FILE__).

EDIT2

また、Ruby v 1.9.3 で導入されたもの/dev/nullを使用して、真の OS に転送できることにも言及する必要があります。File::NULL(jruby1.7)

次に、コード スニペットは次のようになります。

#spec_helper.rb
RSpec.configure do |config|
  original_stderr = $stderr
  original_stdout = $stdout
  config.before(:all) do
    # Redirect stderr and stdout
    $stderr = File.open(File::NULL, "w")
    $stdout = File.open(File::NULL, "w")
  end
  config.after(:all) do
    $stderr = original_stderr
    $stdout = original_stdout
  end
end
于 2013-03-15T12:48:42.687 に答える
30

beforeブロックで出力を行うスタブメソッドを試してください。

before do
  IO.any_instance.stub(:puts) # globally
  YourClass.any_instance.stub(:puts) # or for just one class
end

これは明示的であるため、見逃したくないものを見逃すことはありません。出力を気にせず、上記の方法が機能しない場合は、いつでもIOオブジェクト自体をスタブできます。

before do
  $stdout.stub(:write) # and/or $stderr if needed
end
于 2013-03-15T11:02:09.193 に答える
10

単一のテストの出力を抑制したい場合は、より簡潔な方法があります。

it "should do something with printing" do
  silence_stream(STDOUT) do
    foo.print.should be_true
  end
end

テストでエラーが出力される場合は、に変更することをお勧めしSTDOUTます。STDERR

于 2014-04-29T12:41:30.277 に答える
0

STDOUT をデフォルトとする IO オブジェクトを注入すると便利な場合があります。これにより、必要に応じて出力でアサートすることも容易になります。

例えば

def my_method(arg, io: STDOUT)
  io.puts "hello"
  arg.reverse
end

そして、あなたのテストで:

# Suppress it.

my_method("hi", io: StringIO.new)

# Assert on it.

io = StringIO.new
my_method("hi", io: io)

output = io.tap(&:rewind).read
expect(output).to include("hello")
于 2021-03-17T09:15:28.623 に答える