output matcher

The output matcher provides a way to assert that the block has emitted content to either $stdout or $stderr.

With no arg, passes if the block outputs to_stdout or to_stderr. With a string, passes if the blocks outputs that specific string to_stdout or to_stderr. With a regexp or matcher, passes if the blocks outputs a string to_stdout or to_stderr that matches.

Note: to_stdout and to_stderr work by temporarily replacing $stdout or $stderr, so they’re not able to intercept stream output that explicitly uses STDOUT/STDERR or that uses a reference to $stdout/$stderr that was stored before the matcher is used.

To capture output from any spawned subprocess as well, use to_stdout_from_any_process or to_stderr_from_any_process. Output from any process that inherits the main process’s corresponding standard stream will be captured.

Note: to_stdout_from_any_process and to_stderr_from_any_process use tempfiles to capture output, and are thus significantly (~30x) slower than to_stdout and to_stderr.

Using the output_to_stdout matcher

Given a file named “outputtostdout_spec.rb” with:

RSpec.describe "output.to_stdout matcher" do
  specify { expect { print('foo') }.to output.to_stdout }
  specify { expect { print('foo') }.to output('foo').to_stdout }
  specify { expect { print('foo') }.to output(/foo/).to_stdout }
  specify { expect { }.to_not output.to_stdout }
  specify { expect { print('foo') }.to_not output('bar').to_stdout }
  specify { expect { print('foo') }.to_not output(/bar/).to_stdout }

  # deliberate failures
  specify { expect { }.to output.to_stdout }
  specify { expect { }.to output('foo').to_stdout }
  specify { expect { print('foo') }.to_not output.to_stdout }
  specify { expect { print('foo') }.to output('bar').to_stdout }
  specify { expect { print('foo') }.to output(/bar/).to_stdout }
end

When I run rspec output_to_stdout_spec.rb

Then the output should contain all of these:

11 examples, 5 failures
expected block to output to stdout, but did not
expected block to not output to stdout, but output “foo”
expected block to output “bar” to stdout, but output “foo”
expected block to output “foo” to stdout, but output nothing
expected block to output /bar/ to stdout, but output “foo”

Using the output_to_stderr matcher

Given a file named “outputtostderr.rb” with:

RSpec.describe "output_to_stderr matcher" do
  specify { expect { warn('foo') }.to output.to_stderr }
  specify { expect { warn('foo') }.to output("foo\n").to_stderr }
  specify { expect { warn('foo') }.to output(/foo/).to_stderr }
  specify { expect { }.to_not output.to_stderr }
  specify { expect { warn('foo') }.to_not output('bar').to_stderr }
  specify { expect { warn('foo') }.to_not output(/bar/).to_stderr }

  # deliberate failures
  specify { expect { }.to output.to_stderr }
  specify { expect { }.to output('foo').to_stderr }
  specify { expect { warn('foo') }.to_not output.to_stderr }
  specify { expect { warn('foo') }.to output('bar').to_stderr }
  specify { expect { warn('foo') }.to output(/bar/).to_stderr }
end

When I run rspec output_to_stderr.rb

Then the output should contain all of these:

11 examples, 5 failures
expected block to output to stderr, but did not
expected block to not output to stderr, but output “foo
expected block to output "bar” to stderr, but output “foo
————————————————————–
expected block to output “foo” to stderr, but output nothing
expected block to output /bar/ to stderr, but output “foo

Using the output_to_stdout_from_any_process matcher

Given a file named “outputtostdoutfromanyprocessspec.rb” with:

RSpec.describe "output.to_stdout_from_any_process matcher" do
  specify { expect { system('printf foo') }.to output.to_stdout_from_any_process }
  specify { expect { system('printf foo') }.to output("foo").to_stdout_from_any_process }
  specify { expect { system('printf foo') }.to output(/foo/).to_stdout_from_any_process }
  specify { expect { }.to_not output.to_stdout_from_any_process }
  specify { expect { system('printf foo') }.to_not output("bar").to_stdout_from_any_process }
  specify { expect { system('printf foo') }.to_not output(/bar/).to_stdout_from_any_process }

  # deliberate failures
  specify { expect { }.to output.to_stdout_from_any_process }
  specify { expect { }.to output('foo').to_stdout_from_any_process }
  specify { expect { system('printf foo') }.to_not output.to_stdout_from_any_process }
  specify { expect { system('printf foo') }.to output('bar').to_stdout_from_any_process }
  specify { expect { system('printf foo') }.to output(/bar/).to_stdout_from_any_process }
end

When I run rspec output_to_stdout_from_any_process_spec.rb

Then the output should contain all of these:

11 examples, 5 failures
expected block to output to stdout, but did not
expected block to not output to stdout, but output “foo”
expected block to output “bar” to stdout, but output “foo”
expected block to output “foo” to stdout, but output nothing
expected block to output /bar/ to stdout, but output “foo”

Using the output_to_stderr_from_any_process matcher

Given a file named “outputtostderrfromanyprocessspec.rb” with:

RSpec.describe "output.to_stderr_from_any_process matcher" do
  specify { expect { system('printf foo 1>&2') }.to output.to_stderr_from_any_process }
  specify { expect { system('printf foo 1>&2') }.to output("foo").to_stderr_from_any_process }
  specify { expect { system('printf foo 1>&2') }.to output(/foo/).to_stderr_from_any_process }
  specify { expect { }.to_not output.to_stderr_from_any_process }
  specify { expect { system('printf foo 1>&2') }.to_not output("bar").to_stderr_from_any_process }
  specify { expect { system('printf foo 1>&2') }.to_not output(/bar/).to_stderr_from_any_process }

  # deliberate failures
  specify { expect { }.to output.to_stderr_from_any_process }
  specify { expect { }.to output('foo').to_stderr_from_any_process }
  specify { expect { system('printf foo 1>&2') }.to_not output.to_stderr_from_any_process }
  specify { expect { system('printf foo 1>&2') }.to output('bar').to_stderr_from_any_process }
  specify { expect { system('printf foo 1>&2') }.to output(/bar/).to_stderr_from_any_process }
end

When I run rspec output_to_stderr_from_any_process_spec.rb

Then the output should contain all of these:

11 examples, 5 failures
expected block to output to stderr, but did not
expected block to not output to stderr, but output “foo”
expected block to output “bar” to stderr, but output “foo”
expected block to output “foo” to stderr, but output nothing
expected block to output /bar/ to stderr, but output “foo”