Je teste la classe qui a mis sur la console quelques messages (avec des puts, des avertissements p et etc.). Je me demande simplement s'il est possible de supprimer cette sortie pendant les tests RSpec?
Je supprime la sortie de puts
dans mes classes en redirigeant $stout
Vers un fichier texte. De cette façon, si j'ai besoin de voir la sortie pour une raison quelconque, elle est là mais elle ne brouille pas mes résultats de test.
#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
MODIFIER:
En réponse au commentaire de @MyronMarston, il serait probablement plus intelligent d'insérer simplement les méthodes directement dans before
et after
sous forme de blocs.
#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
Il semble un peu plus propre et garde les méthodes hors de main
. Notez également que si vous utilisez Ruby 2.0, vous pouvez utiliser __dir__
Au lieu de File.dirname(__FILE__)
.
EDIT2
Il convient également de mentionner que vous pouvez transférer vers le véritable système d'exploitation /dev/null
En utilisant File::NULL
Tel qu'il a été introduit dans Ruby v 1.9.3. (Jruby 1.7 )
L'extrait de code se présente alors comme suit:
#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
Essayez les méthodes de stubbing qui font la sortie dans un bloc avant, par exemple.
before do
IO.any_instance.stub(:puts) # globally
YourClass.any_instance.stub(:puts) # or for just one class
end
C'est explicite, donc vous ne manquerez rien que vous ne voulez pas manquer. Si vous ne vous souciez d'aucune sortie et que la méthode ci-dessus ne fonctionne pas, vous pouvez toujours bloquer l'objet IO lui-même:
before do
$stdout.stub(:write) # and/or $stderr if needed
end
Une version Rspec3.0 serait => dans spec_helper.rb
RSpec.configure do |c|
c.before { allow($stdout).to receive(:puts) }
end
il agira comme before(:each)
mais: chacun est par défaut, donc pas besoin de l'écrire explicitement
Testé avec rspec-core (~> 3.4.0)
Dans décrire le bloc que vous pourriez faire
# 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
De cette façon, vous avez l'avantage de basculer la sortie du journal pour des tests spécifiques. Notez que ceci ne le fera pas supprime les avertissements rspec ou les messages de rspec.
Une autre façon de désactiver les avertissements provenant des gemmes:
ajoutez config.warnings = false
à spec_helper
Si vous vouliez supprimer uniquement certaines méthodes d'enregistrement, comme error, info, or warn
, Vous pourriez le faire
allow_any_instance_of(Logger).to receive(:warn).and_return(nil)
Pour désactiver les avertissements provenant de la gemme rspec
allow(RSpec::Support).to receive(:warning_notifier).and_return(nil)
mais cela est généralement déconseillé car il est destiné à vous faire savoir que vous faites quelque chose de malodorant dans vos tests.
Si vous souhaitez supprimer la sortie pour un seul test, il existe un moyen plus concis:
it "should do something with printing" do silence_stream(STDOUT) do foo.print.should be_true end end
Vous souhaiterez peut-être remplacer STDOUT
par STDERR
si votre test affiche une erreur.
Réponse mise à jour pour Rails 5, dans une situation ponctuelle:
before do
RSpec::Mocks.with_temporary_scope do
allow(STDOUT).to receive(:puts)
end
end
Vous pouvez en faire une méthode dans spec_helper si vous le ferez beaucoup.
Après avoir essayé tous ces exemples, j'ai fini par utiliser cette variation qui ne fait pas taire ou mute binding.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