[Tutor] unittest and private methods
lemeia at bigpond.com
Sat Jan 21 07:46:41 CET 2006
> > 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?
Yes - it is __extractTo(self, text, delimiter)
> > 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
> > 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.
I like the term Speculative Generality - never heard that before. If the method was already extremely complicated I would agree that you should only alter when needed. However, this method is simpler in design and I don't see the harm in generalising in this particular case. Once I'd made the decision to generalise it I consequently saw several worthwhile refactoring possibilities in my class, which I shall probably exercise a little later.
> 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
> 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.
> This makes sense to me and I hadn't thought of that in all honesty. I get so involved in object orientated design, I sometimes forget about the convenience of a few general functions to "help out". Would I lose my OO membership card though?
I think I might stick to the public interface testing wherever possible and I have done so with other private methods in my class. This particular one just seemed to benefit from direct testing.
I'm really enjoying Python. I don't like the "sentence structure" quite as much as Smalltalk (ie I like anObject actOn: a untilYouSee: b), but there's something quite friendly about its syntax all the same. I find it much faster to do things in Python even over Visual Basic. I really like developing using OO and so far, Python has been the easiest to adopt (besides Smalltalk perhaps). For some reason I struggled with OO in C++ when I looked into it and Java always seemed to be a big red stop sign for me (not sure why).
More information about the Tutor