wood burning stoves 2.0*
The moose likes Testing and the fly likes Testing private methods Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Android Security Essentials Live Lessons this week in the Android forum!
JavaRanch » Java Forums » Engineering » Testing
Bookmark "Testing private methods" Watch "Testing private methods" New topic
Author

Testing private methods

Garrett Rowe
Ranch Hand

Joined: Jan 17, 2006
Posts: 1296
I know that it is not possible to test private methods with JUnit. But I wonder if the need to do so indicates that I need to expose more methods as public within my API. For example i have the following algorithm:


I would like to write tests for the algorithms individually, but the only thing I can think of to do is to test whether move.execute() is called on the correct Move. Does this indicate that I need to expose more of my API to make my class more testable. What about exposing the methods for testing purposes only?


Some problems are so complex that you have to be highly intelligent and well informed just to be undecided about them. - Laurence J. Peter
Frank Carver
Sheriff

Joined: Jan 07, 1999
Posts: 6920
Some people seem more worried than others by the idea of public and private. Personally, I have no problem with making methods public if they can be tested independently. Several successful programming languages have no concept of private methods.

There is an argument for making a method private if it can change the internal state of the object in an unstable way, but something like your "get list of all possible moves" seems an ideal candidate for a public method.

So, you have asked us if it is a good idea to make your private methods public. In turn, I ask you why you wanted to make them private in the first place. The answer to that question could well help you decide what to do.


Read about me at frankcarver.me ~ Raspberry Alpha Omega ~ Frank's Punchbarrel Blog
Garrett Rowe
Ranch Hand

Joined: Jan 17, 2006
Posts: 1296
I mede them private to simplify the API. Probably not the strongest of arguments but a method that returns a List of all possible moves seems like it should not be called outside of the context of the single method I use it in. Although I expect as soon as I say that, I will need it somewhere else. I guess it just feels like exposing too many public methods invites the possibility of the class being used in a way other than what I intended when it was written. I guess I was just trying to extract away all the implementation details from the public API.
Jeanne Boyarsky
internet detective
Marshal

Joined: May 26, 2003
Posts: 30136
    
150

Garrett,
Some people (myself included) make methods package private - no modifier at all - in that case. It is clear that the method shouldn't be called by third parties, but can still be called by your code and your tests.


[Blog] [JavaRanch FAQ] [How To Ask Questions The Smart Way] [Book Promos]
Blogging on Certs: SCEA Part 1, Part 2 & 3, Core Spring 3, OCAJP, OCPJP beta, TOGAF part 1 and part 2
Frank Carver
Sheriff

Joined: Jan 07, 1999
Posts: 6920
I guess it just feels like exposing too many public methods invites the possibility of the class being used in a way other than what I intended when it was written.

One of the most enlightening things I ever came to understand about software is that things being used in ways you don't plan for is not bad - it's an overwhelmingly good thing. Most of the best-loved software in the world exposes internal APIs for users to use in new and creative ways. If you want your software to be successful, you should too.

Even at the level of methods on objects that only your code and tests use, it can still save you time and heartache in the future if the tools you need for unknown future requirements are already there waiting.

I guess I was just trying to extract away all the implementation details from the public API.

That's a good goal. The way I approach this is to expose methods, but hide classes.

In your example I might create a Move interface with a minimum set of methods applicable to a move, and provide a public method on the class-in-question which returns a java.util.Collection, each element of which is a Move.

I suggest Collection because it is the most general we can get away with. This allows you to actually return a HashSet, an ArrayList, or whatever. And defining each entry to be an interface allows you to mess with the implementing classes as much as you like without breaking current or future code.

I hope you can see that this exposes the "list all moves" functionality for future code (and today's tests) to use, but does not give anything away about the actual implementation.

Does that make any sense?
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24183
    
  34

If a private method needs to be tested, consider whether it ought to be a public method of some other class. In other words, can you extract the functionality out into a smaller class that you can test independently, and then have the original class simply use the new class?


[Jess in Action][AskingGoodQuestions]
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Originally posted by Ernest Friedman-Hill:
If a private method needs to be tested, consider whether it ought to be a public method of some other class. In other words, can you extract the functionality out into a smaller class that you can test independently, and then have the original class simply use the new class?


Exactly! In fact there are people who think you should consider the same for private methods that don't need to be tested...

See also http://c2.com/cgi/wiki?MethodsShouldBePublic


The soul is dyed the color of its thoughts. Think only on those things that are in line with your principles and can bear the light of day. The content of your character is your choice. Day by day, what you do is who you become. Your integrity is your destiny - it is the light that guides your way. - Heraclitus
Garrett Rowe
Ranch Hand

Joined: Jan 17, 2006
Posts: 1296
Originally posted by Ernest Friedman-Hill:
If a private method needs to be tested, consider whether it ought to be a public method of some other class. In other words, can you extract the functionality out into a smaller class that you can test independently, and then have the original class simply use the new class?

So if I get your point, I could extract my three (or so..) private methods into two smaller classes.


Or am I a little off-base with my thinking?
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24183
    
  34

Yes, that's basically it. Of the two proposed small classes, I like the second one better. The first one has too much "data envy", I think, in that it has to root around in Board's data to find its answer.
Garrett Rowe
Ranch Hand

Joined: Jan 17, 2006
Posts: 1296
The first one has too much "data envy", I think, in that it has to root around in Board's data to find its answer.


You're right about that. I refactored to the above mentioned classes before you replied (at least I gave them less absurd names). Anyway the I had to write three new accessor methods in the Board interface to get the job done. It started to smell really bad. I'll probably take Frank's suggestion and move that method back into board class and just make it public. Its not like its exposing any crucial implementation details anyway. I still haven't figured out that TDD style even after the lesson Frank and Ilja gave in the TennisMatch thread. I get too eager to keep writing methods before testing the ones I've already written. Plus I always get stuck at that "Well, my current tests are passing, but I have no idea what the next test should do" phase. Anyway, thanks for the quick course in OO-design guys.
Frank Carver
Sheriff

Joined: Jan 07, 1999
Posts: 6920
Just as an aside, the second class you gave gets me itching for a spot of polymorphism. I get uncomfaortable with methods or classes which seem too similar to each other. How about something like:



Then your client code can be something more generic such as:



I'm sure this is not really the overall algorithm you plan to use, but it's the decomposition into objects which decouples the choice of stragtegies from the code which uses them which I'm driving at. To change or add picker algorithms, just change the array definition, no changes needed to the overall evaluation code.

Thoughts?
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Testing private methods
 
Similar Threads
How to test private method in JUnit?
need some help with recursion (Connect 4 program)
unit testing without brittle code
testing private methods with junit?
Testing Private Methods