On Fri, 2002-08-16 at 20:41, Gray, Jeff wrote:
> I'm sorta new to the whole unit testing thing, and my only prior exposure to
> software testing is using DejaGnu/Expect.  I'm just starting to use
> Test::Unit, and I have a case where a certain action should produce a
> warning message.  There is no other side effect that can be tested to make
> sure the condition that produced the warning was indeed exercised properly,
> just the appearance of the message.
> 
> I don't see any obvious assertion in Test::Unit that allows checking of I/O
> to $stdout/$stderr.  What's a good way to test for such a case?

If something is hard to test, that's a good indication that the design
needs to change.

In your case, your object is writing to stdout or stderr.  Because it is
accessing the output streams through a global variable, you cannot
intercept those calls and test that they are correct.

A unit test is meant to test a unit (a class, for example) in
isolation.  That means you have to be able to isolate the unit from its
environment, which means it should not read or write global variables. 
In fact it should only make calls to objects that it has as instance
variables or are passed to it's methods as parameters.

I would therefore change my design so that the object under test is
given a stream object to which it writes messages.  In my unit tests, I
would pass in a mock stream object that asserts that it is called
correctly.  In my application and end-to-end functional tests, I would
pass in a reference to stdout or stderr so that output actually gets
written.

I have written a Test::Mock package that you might help you mock the
output stream object.  You can get it from here:

http://www.ruby-lang.org/~knu/cgi-bin/cvsweb.cgi/rough/lib/testmock/

Cheers,
	Nat.


-- 
Dr. Nathaniel Pryce, Technical Director, B13media Ltd.
Studio 3a, 22-24 Highbury Grove, London N5 2EA, UK
http://www.b13media.com