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).

2voto

cfeduke Points 13153

Après avoir creusé, J'ai trouvé ceci .

Ma solution a fini par ressembler à ceci :

# something.rb
class Something
    def initialize(kernel=Kernel)
        @kernel = kernel
    end

    def process_arguments(args)
        @kernel.exit
    end
end

# something_spec.rb
require 'something'
describe Something do
    before :each do
        @mock_kernel = mock(Kernel)
        @mock_kernel.stub!(:exit)
    end

    it "should exit cleanly" do
        s = Something.new(@mock_kernel)
        @mock_kernel.should_receive(:exit)
        s.process_arguments(["-h"])
    end
end

1voto

David Nedrow Points 404

J'ai dû mettre à jour la solution fournie par @Greg en raison de nouvelles exigences en matière de syntaxe.

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 do |block|
    "expected block to call exit(#{exp_code}) but exit" +
        (actual.nil? ? " not called" : "(#{actual}) was called")
  end
  failure_message_when_negated do |block|
    "expected block not to call exit(#{exp_code})"
  end
  description do
    "expect block to call exit(#{exp_code})"
  end
  supports_block_expectations
end

1voto

abhchand Points 313

J'utilise la solution de @Greg depuis des années maintenant, mais je l'ai modifiée pour qu'elle fonctionne avec RSpec 3+.

J'ai également modifié le code pour qu'il vérifie facultativement l'état de sortie, ce qui est beaucoup plus souple.

Utilisation

expect { ... }.to call_exit
expect { ... }.to call_exit.with(0)

expect { ... }.to_not call_exit
expect { ... }.to_not call_exit.with(0)

Source :

RSpec::Matchers.define :call_exit do
  actual_status = nil

  match do |block|
    begin
      block.call
    rescue SystemExit => e
      actual_status = e.status
    end

    actual_status && (expected_status.nil? || actual_status == expected_status)
  end

  chain :with, :expected_status

  def supports_block_expectations?
    true
  end

  failure_message do |block|
    expected = 'exit'
    expected += "(#{expected_status})" if expected_status

    actual = nil
    actual = "exit(#{actual_status})" if actual_status

    "expected block to call `#{expected}` but " +
      (actual.nil? ? 'exit was never called' : "`#{actual}` was called")
  end

  failure_message_when_negated do |block|
    expected = 'exit'
    expected += "(#{expected_status})" if expected_status

    "expected block not to call `#{expected}`"
  end

  description do
    expected = 'exit'
    expected += "(#{expected_status})" if expected_status

    "expect block to call `#{expected}`"
  end
end

0voto

Josh Pinter Points 3814

Je cherche juste le code d'état de sortie d'une commande.

Si tout ce que vous faites est de tester le code d'état de sortie d'une commande, vous pouvez faire quelque chose comme ceci :

describe Something do
  it "should exit without an error" do
    expect( system( "will_exit_with_zero_status_code" ) ).to be true
  end

  it "should exit with an error" do
    expect( system( "will_exit_with_non_zero_status_code" ) ).to be false
  end
end

Cela fonctionne parce que system reviendra :

  • true lorsque la commande se termine avec un code d'état "0" (c'est-à-dire aucune erreur).
  • false lorsque la commande se termine avec un code d'état non nul (c'est-à-dire une erreur).

Et si vous voulez mettre en sourdine la sortie du system de la sortie de votre documentation rspec, vous pouvez la rediriger comme suit :

system( "will_exit_with_zero_status_code", [ :out, :err ] => File::NULL )

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