Prev: Design Questions about static factory classes
Next: JavaSE/EE + Tomcat 6 + Windows service on 64 bit
From: Rhino on 21 May 2010 19:38 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 21 May 2010 20:27 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 22 May 2010 14:14 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 23 May 2010 10:03 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 23 May 2010 10:25
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 |