有没有办法访问RSpec示例中的Ruby警告列表?我在我正在测试的库中收到以下错误,并希望为它编写单元测试。
warning: previous definition of BUILD_FILE was here
答案 0 :(得分:2)
我最终启动了一个新流程并评估流程输出。在我的例子中,问题是一个重新定义的常量,所以我通过将类加载到新的Ruby进程中然后使用IO流来读取输出来进行测试:
it 'should not redefine BUILD_FILE constant' do
root_path = "#{File.dirname(__FILE__)}/../../../../"
cmd = "load \"#{root_path}libraries/build_file.rb\";"
ruby_path = 'C:/opscode/chefdk/embedded/bin/ruby.exe'
pipe_cmd_in, pipe_cmd_out = IO.pipe
pid = Process.spawn("#{ruby_path} -e '#{cmd} #{cmd}'", :out => pipe_cmd_out, :err => pipe_cmd_out)
Process.wait(pid)
pipe_cmd_out.close
output = pipe_cmd_in.read
puts "OUTPUT = #{output}"
expect(output).to_not match(/previous\sdefinition\sof\sBUILD_FILE/)
end
答案 1 :(得分:1)
Ruby警告转到$stderr
,因此您可以使用一个侦测写入警告的对象来包装它:
在spec / support / warning_spying_stderr.rb中:
require 'delegate'
class WarningSpyingIO < SimpleDelegator
attr_reader :strings
def initialize(delegate)
@strings = []
super
end
def write(string)
if string.include? 'warning: ' # in case anything other than a Ruby warning goes to $stderr
@strings << string
end
__getobj__.write string
end
end
$stderr = WarningSpyingIO.new $stderr
在spec / warning_spec.rb中:
describe "My code" do
it "has no warnings" do
FOO = 'foo'
FOO = 'bar'
expect($stderr.strings).to be_empty
end
end
规范以
失败expected `[
"spec/warning_spec.rb:4: warning: already initialized constant FOO\n",
"spec/warning_spec.rb:3: warning: previous definition of FOO was here\n"
].empty?` to return true, got false
为了方便起见,我在规范中放置了生成测试警告的行,但是对于$stderr
被劫持后发出的任何警告,它应该同样有效。
我没有遇到需要在RSpec退出之前停止间谍活动,但如果你这样做就可以做到
$stderr = $stderr.__getobj__
在你想要停止间谍活动的时候。