35

私がしたいのはruby sayhello.rb、コマンドラインで実行してから、Hello from Rspec.

私はこれでそれを持っています:

class Hello
  def speak
    puts 'Hello from RSpec'
  end
end

hi = Hello.new #brings my object into existence
hi.speak

ここで、コマンドライン出力が実際に「I like Unix」ではなく「Hello from RSpec」であることを確認するために、rspec でテストを作成したいと考えています。

動作していません。私は現在、これを私の sayhello_spec.rb ファイルに持っています

require_relative 'sayhello.rb' #points to file so I can 'see' it

describe "sayhello.rb" do
  it "should say 'Hello from Rspec' when ran" do        
    STDOUT.should_receive(:puts).with('Hello from RSpec')    
  end
end

また、RSPEC でテストがどのように見えるかを実際に確認する必要があります。

4

5 に答える 5

31

最良の方法は、出力マッチャーで rspec ビルドを使用することだと思いますhttps://www.relishapp.com/rspec/rspec-expectations/docs/built-in-matchers/output-matcher

たとえば、これはあなたのクラスです

class MakeIt
  def awesome(text)
    puts "Awesome #{text}"
  end
end

そしてあなたのテスト

describe MakeIt do
  describe '#awesome' do
    it 'prints awesome things' do
      expect do
        MakeIt.new.awesome('tests')
      end.to output('Awesome tests').to_stdout
    end

    it 'does not print not awesome things' do
      expect do
        MakeIt.new.awesome('tests')
      end.to_not output('Not awesome tests').to_stdout
    end
  end
end

素敵で、きれいで、本のそばに!

于 2016-07-14T15:03:10.290 に答える
16

以前の回答/コメントに基づいて、gem なしで新しい構文を使用するソリューションは次のようになります。

describe "sayhello.rb" do
  it "should say 'Hello from Rspec' when run" do        
    expect(STDOUT).to receive(:puts).with('Hello from RSpec')
    require_relative 'sayhello.rb'  # load/run the file 
  end
end
于 2015-05-20T07:24:15.490 に答える
12

メソッドを追加するRails のactive_supportライブラリを使用して、これを解決できます。capture

require 'active_support/core_ext/kernel/reporting'
require_relative 'sayhello'

describe Hello do
  it "says 'Hello from RSpec' when ran" do
    output = capture(:stdout) do
      hi = Hello.new
      hi.speak
    end
    expect(output).to include 'Hello from RSpec'
  end
end
于 2014-01-09T16:02:24.533 に答える
3

bswinnerton の答えにいくぶん似ていますが、puts出力をキャプチャしてから、ライブラリに依存する方法を使用せずに、キャプチャした出力に対してテストすることができますcapture(誰かが言及した方法は、Rails 5 で非推奨になっています)。

Ruby には という名前のグローバル変数が$stdoutあり、デフォルトでは定数STDOUT. STDOUTruby プロセスの stdout ストリームにデータを送信するものです (「ストリーム」がここで正しい用語かどうかはわかりません)。基本的に単純なケースSTDOUT.puts("foo")では、端末ウィンドウに「foo\n」が表示されます。 変数名は、再割り当てしない限り$stdout.puts("foo")参照するため、同じことを行います(ここで重要なポイント)。最後に、 のシンタックス シュガーです。 $stdoutSTDOUT puts("foo")$stdout.puts("foo")

その場合の戦略は、コードの実行後に検査できる$stdoutローカルIOインスタンスに再割り当てし、その内容に「Hello from RSpec」が表示されるかどうかを確認することです。

これがどのように機能するか:

describe "sayhello.rb" do
  it "should say 'Hello from Rspec' when ran" do        
    $stdout = StringIO.new

    # run the code
    # (a little funky; would prefer Hello.new.speak here but only changing one thing at a time)
    require_relative 'sayhello.rb' 

    $stdout.rewind   # IOs act like a tape so we gotta rewind before we play it back  

    expect($stdout.gets.strip).to eq('Hello from Rspec')
  end
end
于 2016-01-07T23:25:02.120 に答える