54 votes

Comment puis-je valider les sorties et les abandons dans RSpec ?

J'essaie de spécifier des comportements pour les arguments de ligne de commande que mon script reçoit pour s'assurer que toute validation passe. Certains de mes arguments de ligne de commande auront pour résultat abort ou exit est invoqué parce que les paramètres fournis sont manquants ou incorrects.

J'essaie quelque chose comme ça, mais ça ne marche pas :

# something_spec.rb
require 'something'
describe Something do
    before do
        Kernel.stub!(:exit)
    end

    it "should exit cleanly when -h is used" do
        s = Something.new
        Kernel.should_receive(:exit)
        s.process_arguments(["-h"])
    end
end

Le site exit se déclenche proprement, empêchant RSpec de valider le test (j'obtiens "SystemExit : exit").

J'ai également essayé de mock(Kernel) mais cela ne fonctionne pas non plus comme je le voudrais (je ne vois pas de différence notable, mais c'est probablement parce que je ne suis pas sûr de la façon de simuler le noyau et de m'assurer que le noyau simulé est utilisé dans mon fichier Something classe).

31voto

Markus Strauss Points 737

Essayez ceci :

module MyGem
  describe "CLI" do
    context "execute" do

      it "should exit cleanly when -h is used" do
        argv=["-h"]
        out = StringIO.new
        lambda { ::MyGem::CLI.execute( out, argv) }.should raise_error SystemExit
      end

    end
  end
end

0 votes

Avertissement : Nous avons eu des problèmes avec une solution similaire parce que RSpec vraisemblablement exit lorsque les attentes ne sont pas satisfaites, nous pourrions donc finir par sauver l'interface RSpec exit au lieu des nôtres, etc.

24voto

Dennis Points 5020

En utilisant la nouvelle syntaxe RSpec :

expect { code_that_exits }.to raise_error(SystemExit)

Si quelque chose est imprimé sur STDOUT et que vous voulez le tester aussi, vous pouvez faire quelque chose comme :

context "when -h or --help option used" do
  it "prints the help and exits" do
    help = %Q(
      Usage: my_app [options]
        -h, --help                       Shows this help message
    )

    ARGV << "-h"
    expect do
      output = capture_stdout { my_app.execute(ARGV) }
      expect(output).to eq(help)
    end.to raise_error(SystemExit)

    ARGV << "--help"
    expect do
      output = capture_stdout { my_app.execute(ARGV) }
      expect(output).to eq(help)
    end.to raise_error(SystemExit)
  end
end

capture_stdout est défini comme indiqué dans Test de la sortie vers la ligne de commande avec RSpec .

Mise à jour : Envisagez d'utiliser RSpec output comparateur de prix au lieu de capture_stdout

19voto

Greg Points 783

Merci pour la réponse Markus. Une fois que j'ai eu cet indice, j'ai pu mettre en place un bon matcheur pour une utilisation future.

it "should exit cleanly when -h is used" do
  lambda { ::MyGem::CLI.execute( StringIO.new, ["-h"]) }.should exit_with_code(0)
end
it "should exit with error on unknown option" do
  lambda { ::MyGem::CLI.execute( StringIO.new, ["--bad-option"]) }.should exit_with_code(-1)
end

Pour utiliser cet assortiment, ajoutez ceci à vos bibliothèques ou à vos aide-spécifiques :

RSpec::Matchers.define :exit_with_code do |exp_code|
  actual = nil
  match do |block|
    begin
      block.call
    rescue SystemExit => e
      actual = e.status
    end
    actual and actual == exp_code
  end
  failure_message_for_should do |block|
    "expected block to call exit(#{exp_code}) but exit" +
      (actual.nil? ? " not called" : "(#{actual}) was called")
  end
  failure_message_for_should_not do |block|
    "expected block not to call exit(#{exp_code})"
  end
  description do
    "expect block to call exit(#{exp_code})"
  end
end

15voto

thisismydesign Points 751

Il n'est pas nécessaire de recourir à des appariements personnalisés ou à des blocs de secours, tout simplement :

expect { exit 1 }.to raise_error(SystemExit) do |error|
  expect(error.status).to eq(1)
end

Je dirais que c'est supérieur parce que c'est explicite et simple Rspec.

4voto

Kris Points 3781

Ce n'est pas joli, mais je l'ai utilisé :

begin
  do_something
rescue SystemExit => e
  expect(e.status).to eq 1 # exited with failure status
  # or
  expect(e.status).to eq 0 # exited with success status
else
  expect(true).eq false # this should never happen
end

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X