Подтвердить что ты не робот

Подавлять вывод консоли во время тестов RSpec

Я тестирую класс, который помещает на консоль некоторые сообщения (с puts, p предупреждениями и т.д.). Мне просто интересно, есть ли способность подавлять этот вывод во время тестов RSpec?

4b9b3361

Ответ 1

Я подавляю вывод 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

EDIT:

В ответ на комментарий @MyronMarston, вероятно, было бы разумнее просто вставлять методы непосредственно в before и after в виде блоков.

#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

Также следует упомянуть, что вы можете пересылать true os /dev/null с помощью File::NULL, как он был введен в Ruby v 1.9.3. (jruby 1.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

Ответ 2

Попробуйте методы stubbing, которые делают вывод в переднем блоке, например

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

Это явно, поэтому вы не пропустите ничего, что вы не хотите пропустить. Если вам не нужен какой-либо вывод, и описанный выше метод не работает, вы всегда можете заглушить сам объект ввода-вывода:

before do
  $stdout.stub(:write) # and/or $stderr if needed
end

Ответ 3

Версия Rspec3.0 будет = > в spec_helper.rb

RSpec.configure do |c|
  c.before { allow($stdout).to receive(:puts) }
end

он будет действовать как before(:each)

но: каждый по умолчанию, поэтому нет необходимости явно писать его

Ответ 4

Протестировано с помощью rspec-core (~ > 3.4.0)

В описываемом блоке вы можете сделать

# spec_helper.rb
def suppress_log_output
  allow(STDOUT).to receive(:puts) # this disables puts
  logger = double('Logger').as_null_object
  allow(Logger).to receive(:new).and_return(logger)
end

# some_class_spec.rb
RSpec.describe SomeClass do
  before do
    suppress_log_output
  end
end

Таким образом, у вас есть преимущество переключения вывода журнала для конкретных тестов. Заметьте, что этот не будет подавлять предупреждения rspec или сообщения из rspec.

Другой способ отключить предупреждения, исходящие из драгоценных камней:

добавить config.warnings = false в spec_helper

Если вы хотите подавить только определенные методы регистрации, например error, info, or warn, вы можете сделать

allow_any_instance_of(Logger).to receive(:warn).and_return(nil)

Чтобы отключить предупреждения, исходящие из драгоценного камня rspec

allow(RSpec::Support).to receive(:warning_notifier).and_return(nil)

но это, как правило, обескураживает, потому что это подразумевается как способ сообщить вам, что вы делаете что-то вонючее в своих тестах.

Ответ 5

Если вы хотите подавить вывод для одного теста, есть более сжатый способ:

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

Вы можете изменить STDOUT на STDERR, если ваш тест печатает ошибку.

Ответ 6

Обновлен ответ для Rails 5 в разовой ситуации:

before do
  RSpec::Mocks.with_temporary_scope do
    allow(STDOUT).to receive(:puts)
  end
end

Вы можете сделать это в методе spec_helper, если вы будете делать это много.

Ответ 7

Перепробовав все эти примеры, я закончил тем, что использовал эту вариацию, которая не заставляет замолчать и не отключает связывание .pry

# frozen_string_literal: true

RSpec.configure do |config|
  config.before(:each) do
    allow($stdout).to receive(:puts)
    allow($stdout).to receive(:write)
  end
end