18

我想做的是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

现在我想在 rspec 中编写一个测试来检查命令行输出实际上是“Hello from RSpec”而不是“我喜欢 Unix”

不工作。我目前在我的 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

有人可以指出我正确的方向吗?

4

4 回答 4

26

这是一个很好的方法来做到这一点。从hirb test_helper 源复制:

def capture_stdout(&block)
  original_stdout = $stdout
  $stdout = fake = StringIO.new
  begin
    yield
  ensure
    $stdout = original_stdout
  end
  fake.string
end

像这样使用:

output = capture_stdout { Hello.new.speak }
output.should == "Hello from RSpec\n"
于 2012-07-05T17:39:34.383 回答
2

quietly命令可能是您想要的(融入 ActiveSupport,请参阅api.rubyonrails.org上的文档)。下面的 RSpec 代码片段显示了如何确保在 stderr 上没有输出,同时使 stdout 静音。

quietly do                        # silence everything
  commands.each do |c|
    content = capture(:stderr) {  # capture anything sent to :stderr
      MyGem::Cli.start(c)
    }
    expect(content).to be_empty, "#{c.inspect} had output on stderr: #{content}"
  end
end
于 2013-08-17T20:06:09.077 回答
1

因此,您不必更改主要的 ruby​​ 代码,我刚刚发现您可以执行以下操作:

def my_meth
  print 'Entering my method'
  p 5 * 50
  puts 'Second inside message'
end

describe '#my_meth' do
  it 'puts a 2nd message to the console' do
    expect{my_meth}.to output(/Second inside message/).to_stdout
  end
end

在检查所需的输出文本时,我在 / / 中使用它,Regexp因为经过多次测试并环顾四周,STDOUT 就是输出的所有内容,所以我发现使用正则表达式更好,这样你就可以检查整个 STDOUT您想要的确切文本。就像我说的那样,它在终端中运行得非常完美。

//只是不得不分享这个,我花了好几天才弄明白。

于 2019-12-05T22:15:54.870 回答
-5
it "should say 'Hello from Rspec' when run" do        
  output = `ruby sayhello.rb`
  output.should == 'Hello from RSpec'   
end
于 2013-12-07T16:48:42.927 回答