[Tutor] unittest and private methods

Kent Johnson kent37 at tds.net
Fri Jan 20 12:06:23 CET 2006


lemeia wrote:
> I currently have a class where I have quite a few private methods.
> One
of these methods is a small general utility that extracts characters
from provided text up until it reaches a delimiter. Something like
extractTo(self, text, delimiter).
> 
> It's not a relevant interface to the class, just a utility for the
class' public methods, which is why I've made it private. That seems to
be a logical decision to me.

Yes, that is good reasoning. When you say it is private, do you mean the 
name starts with two underscores?
> 
> However, the public methods within the class that call it currently
only do so to extract numeric events from the text. extractTo is a
little more generalised than that and so I decided that I would use
unittest to build test cases for the extractTo method and exercise it to
its fullest in case the class requires its extended functionality in the
future.
> 
> You'll probably see what my problem is. I can't exercise this method
directly from an external test case as the method is not part of the
class' public interface. If I call a method in the interface that
currently utilises this private method I'm not testing the method as
fully as I would like.

I'm not sure I understand this part. You mean the private methods have 
capabilities that can't currently be exercised through the public 
interface? That smells of "Speculative Generality" - writing code 
because you think you might need it later. If that is the case the best 
answer might be to rip it out and wait until you need it.
> 
> Now I can build arbitrary interfaces into my class just for testing
this method but that sounds like a messy way to maintain a program.
Additionally, I could make this method public, but that also seems like
an unsatisfactory solution.
> 
> The example isn't so important to my question, but I wanted to give
some context before asking......
> 
> Is there a way to specifically target and unit test private methods
> in
a class via unittest without testing them through the class' public
interface?

Python's notion of privacy is pretty weak. I would have no problem with 
a unit test that called single-underscore methods in the class under 
test. Unit test purists object to this, saying a class should only be 
tested through its public interface, but "practicality beats purity" in 
my mind.

Rereading your mail another possibility comes to mind. It sounds like 
extractTo() is a general-purpose function that is used for a specific 
purpose by the module you are testing. Why not extract extractTo to a 
utility module? Then you can test it as much as you like in the unit 
tests for the utility and you can reuse it in other code if the need 
arises. Almost all of my projects have 'util' packages containing 
collections of miscellaneous useful stuff. The utils have their own unit 
tests and get included as needed in other modules and projects.

Kent



More information about the Tutor mailing list