From: Mauricio Fernandez Date: 2006-03-20T21:12:26+09:00 Subject: Re: capturing the stdout On Mon, Mar 20, 2006 at 07:39:02PM +0900, Robert Klemme wrote: > >I am running a test case and need it capture the output it gives me. > > > >require 'stringio' > >old_stdout = $stdout > >$stdout = StringIO.new > >........... > >@reqout = $stdout.string > >$stdout = old_stdout > > > > > >the above code captures the stdout if something written explicily (like > >puts). > >but it doesnot capture the output or running a testcase. > >i want to capture the results if the testcases. > >is there a way it could be done. > > You probably must redirect $defout also. Other than that doing it > externally (i.e. in the calling process) might be an option, too. IIRC $defout is deprecated. You can separate the output (from the code being tested) from the information displayed by Test::Unit as follows: include Test::Unit::UI out = StringIO.new "" test_out = StringIO.new "" $stdout = out ret = Console::TestRunner.new(my_test_suite, NORMAL, test_out).start $stdout = STDOUT # "actual" stdout in out.string # Test::Unit info in test_out.string If you also want to capture the stdout from subprocesses, you need something like begin old_stdout = STDOUT.dup STDOUT.reopen("mytempfile", "w") ... # create the TestRunner, possibly redirecting its output as shown above; # fork, system, ``, etc. in the tested code will be redirected to the # tempfile ... ensure STDOUT.reopen(old_stdout) end Silly example of the former: RUBY_VERSION # => "1.8.4" require 'stringio' require 'test/unit/ui/console/testrunner' class Foo def foo(a,b) if b > 3 puts a + b else puts a - b end a * b end end class TC_Foo < Test::Unit::TestCase def setup; @foo = Foo.new end def test_foo assert_equal(8, @foo.foo(2, 4)) end end include Test::Unit::UI out = StringIO.new "" test_out = StringIO.new "" $stdout = out ret = Console::TestRunner.new(TC_Foo.suite, NORMAL, test_out).start $stdout = STDOUT puts "Output:" out.string.each{|x| puts "-> #{x}"} puts "----" puts "Test (#{ret.passed? ? "passed" : "failed"}):" test_out.string.each{|x| puts "->> #{x}"} # >> Output: # >> -> 6 # >> ---- # >> Test (passed): # >> ->> Loaded suite TC_Foo # >> ->> Started # >> ->> . # >> ->> Finished in 0.000601 seconds. # >> ->> # >> ->> 1 tests, 1 assertions, 0 failures, 0 errors -- Mauricio Fernandez - http://eigenclass.org - singular Ruby