使用RSpec测试输出到命令行

时间:2012-07-05 17:15:45

标签: ruby testing rspec

我想要的是在命令行上运行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中编写一个测试来检查命令行输出实际上是“来自RSpec的Hello” 而不是“我喜欢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 个答案:

答案 0 :(得分:25)

这是一个非常好的方法。复制自hirb test_helper source

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"

答案 1 :(得分: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

答案 2 :(得分:0)

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

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一样在//内部使用了它,因为经过许多多次maaany测试并环顾四周,STDOUT是输出的所有内容,因此我发现使用Regex更好因此您可以在整个STDOUT上检查所需的确切文本。 就像我说的那样,它在终端中的工作非常完美。

//只需要分享一下,我花了几天的时间就弄清楚了。

答案 3 :(得分:-5)

it "should say 'Hello from Rspec' when run" do        
  output = `ruby sayhello.rb`
  output.should == 'Hello from RSpec'   
end