Я тестирую класс, который помещает на консоль некоторые сообщения (с puts, p предупреждениями и т.д.). Мне просто интересно, есть ли способность подавлять этот вывод во время тестов RSpec?
Подавлять вывод консоли во время тестов RSpec
Ответ 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