• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Testing private methods

 
Ranch Hand
Posts: 1296
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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?
 
Sheriff
Posts: 7001
6
Eclipse IDE Python C++ Debian Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Garrett Rowe
Ranch Hand
Posts: 1296
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
author & internet detective
Posts: 41860
908
Eclipse IDE VI Editor Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Frank Carver
Sheriff
Posts: 7001
6
Eclipse IDE Python C++ Debian Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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?
 
author and iconoclast
Posts: 24207
46
Mac OS X Eclipse IDE Chrome
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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?
 
author
Posts: 14112
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
 
Garrett Rowe
Ranch Hand
Posts: 1296
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 24207
46
Mac OS X Eclipse IDE Chrome
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 1296
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 7001
6
Eclipse IDE Python C++ Debian Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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?
 
Don't get me started about those stupid light bulbs.
reply
    Bookmark Topic Watch Topic
  • New Topic