web-dev-qa-db-fra.com

Supprimer la sortie de la console pendant les tests RSpec

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?

42
demas

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
40
Charles Caldwell

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
27

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

19
jaiks

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.

14
lfender6445

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.

10
shock_one

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.

6
concept47

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
0
Chris Hough