From: Rhino on
Patricia Shanahan <pats(a)acm.org> wrote in
news:YfqdnWRcetdwlWrWnZ2dnUVZ_jmdnZ2d(a)earthlink.com:

> Rhino wrote:
>> What is a good JUnit test for a method that takes no input
>> parameters, throws no exceptions, and returns no values but only
>> writes information to a console?
>>
>> In addition to the getLocales() method which we're discussing in
>> another thread, I have a displayLocales() method which begins by
>> calling getLocales (), then writes the information it got from
>> getLocales() to the console.
>>
>> I'm at a loss in trying to think of something to test in a JUnit test
>> for this method.
>>
>> Is there some way to prove that the console was written to? Is there
>> some way to intercept the output to be sure that the right things
>> were written? Or that at least the right number of lines was written
>> and a few of the key Locales appeared on the console? Or is none of
>> that necessary for a method with these characteristics?
>>
>
> This sort of thing illustrates a somewhat subtle advantage of test
> driven design. There are often small differences in an interface
> design that make all the difference in how easy it is to test. Test
> driven design naturally leads to a preference for designs that can be
> tested over designs that are harder to test.
>
Maybe I'm reading too much into your remarks but are you hinting that
maybe I shouldn't even have such a method? Just stick with a getLocales()
method and leave the classes that use it to have their own code for
displaying the Locales? Because that's what I've been considering as I
struggled with how to test displayLocales().

It _is_ just a convenience method, a way to do in one line what would
have taken four or five lines if it didn't exist. As such, its existence
is no more defensible than any other convenience method. Then again, it
IS convenient - I've used it very occasionally to remind myself which
Locales are available in my JVM - so I might miss it (slightly) if it
weren't there.

> For example, many output methods could be written to take a
> PrintWriter or PrintStream parameter. Methods written that way are
> easy to test by giving them a PrintWriter based on a StringWriter or a
> PrintStream based on a ByteArrayOutputStream.
>
One such example is Properties, which has an overloaded list() method
that writes to either a PrintWriter or a PrintStream.... If I recall
correctly, it was this class or something similar which inspired me to
write displayLocales() in the first place several years back.


> You still need a system level test procedure that checks that output
> is going to the right destination, but that test can even be manual,
> and does not need to deal with the unit test level details.
>
> Writing the tests after defining the method you are stuck with
> workarounds such as temporarily replacing System.out.
>

So, if I keep the method, I should capture the System.out and test it the
same way I did for getLocales: verify that the right number of Locales
was displayed and that a handful of the key ones, like en_US, were among
those displayed? I can do that, now that Arne showed me the technique
elsewhere in this thread.

--
Rhino
From: Daniel Pitts on
On 5/21/2010 1:25 PM, Rhino wrote:
> What is a good JUnit test for a method that takes no input parameters,
> throws no exceptions, and returns no values but only writes information to
> a console?
>
> In addition to the getLocales() method which we're discussing in another
> thread, I have a displayLocales() method which begins by calling getLocales
> (), then writes the information it got from getLocales() to the console.
>
> I'm at a loss in trying to think of something to test in a JUnit test for
> this method.
>
> Is there some way to prove that the console was written to? Is there some
> way to intercept the output to be sure that the right things were written?
> Or that at least the right number of lines was written and a few of the key
> Locales appeared on the console? Or is none of that necessary for a method
> with these characteristics?
Instead of writing to the console, your method should write to a
stream/writer/etc... which was configured in the constructor of the
object which the method was called on.

Then, you can create a new instance of that class, pass in a
StringWriter, and later retrieve the string that was written to it, and
verify the contents.

--
Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
From: Rhino on
Daniel Pitts <newsgroup.spamfilter(a)virtualinfinity.net> wrote in
news:BxFJn.20590$gv4.16514(a)newsfe09.iad:

> On 5/21/2010 1:25 PM, Rhino wrote:
>> What is a good JUnit test for a method that takes no input
>> parameters, throws no exceptions, and returns no values but only
>> writes information to a console?
>>
>> In addition to the getLocales() method which we're discussing in
>> another thread, I have a displayLocales() method which begins by
>> calling getLocales (), then writes the information it got from
>> getLocales() to the console.
>>
>> I'm at a loss in trying to think of something to test in a JUnit test
>> for this method.
>>
>> Is there some way to prove that the console was written to? Is there
>> some way to intercept the output to be sure that the right things
>> were written? Or that at least the right number of lines was written
>> and a few of the key Locales appeared on the console? Or is none of
>> that necessary for a method with these characteristics?
> Instead of writing to the console, your method should write to a
> stream/writer/etc... which was configured in the constructor of the
> object which the method was called on.
>
> Then, you can create a new instance of that class, pass in a
> StringWriter, and later retrieve the string that was written to it,
> and verify the contents.
>

Or pass a reference to the stream/writer to the method, like
Properties.list() does?

Thanks for the suggestion. I would like to make my code as good as I can
and if writing to a stream or writer is better, I'm game to do that.
--
Rhino
From: Rhino on
Daniel Pitts <newsgroup.spamfilter(a)virtualinfinity.net> wrote in
news:BxFJn.20590$gv4.16514(a)newsfe09.iad:

> On 5/21/2010 1:25 PM, Rhino wrote:
>> What is a good JUnit test for a method that takes no input
>> parameters, throws no exceptions, and returns no values but only
>> writes information to a console?
>>
>> In addition to the getLocales() method which we're discussing in
>> another thread, I have a displayLocales() method which begins by
>> calling getLocales (), then writes the information it got from
>> getLocales() to the console.
>>
>> I'm at a loss in trying to think of something to test in a JUnit test
>> for this method.
>>
>> Is there some way to prove that the console was written to? Is there
>> some way to intercept the output to be sure that the right things
>> were written? Or that at least the right number of lines was written
>> and a few of the key Locales appeared on the console? Or is none of
>> that necessary for a method with these characteristics?
> Instead of writing to the console, your method should write to a
> stream/writer/etc... which was configured in the constructor of the
> object which the method was called on.
>
> Then, you can create a new instance of that class, pass in a
> StringWriter, and later retrieve the string that was written to it,
> and verify the contents.
>

Just to be clear, let's say that the class containing my displayLocales()
method is called LocalizationUtils and it is a static factory class. Are
you saying that the stream or writer or whatever should be configured in
the constructor of LocalizationUtils or in the class which CALLS
LocalizationUtils? I'm assuming you mean the latter but I just want to be
sure.

--
Rhino
From: Lew on
On 05/23/2010 10:03 AM, Rhino wrote:
> Just to be clear, let's say that the class containing my displayLocales()
> method is called LocalizationUtils and it is a static factory class. Are
> you saying that the stream or writer or whatever should be configured in
> the constructor of LocalizationUtils or in the class which CALLS
> LocalizationUtils? I'm assuming you mean the latter but I just want to be
> sure.

He was saying in the constructor of LocalizationUtils. However, static
factory classes have their own rules.

A (usually - always the disclaimer) better pattern is to include the Locale as
an argument to the factory method. Static state is an antipattern.

public class LocalizationUtils
{
/** Don't forget the private constructor! */
private LocalizationUtils(){}

/**
* Foo factory with default Locale.
* @return Foo instance with default Locale.
*/
public static Foo getFooInstance()
{
return new SubtypeOfFoo();
}

/**
* Foo factory with custom Locale.
* @param locale custom Locale.
* @return Foo instance with custom Locale.
*/
public static Foo getFooInstance( Locale locale )
{
return new SubtypeOfFoo( locale );
}
}

Remember, the only hard and fast rule of programming is that there are no hard
and fast rules of programming.

--
Lew