[Tutor] unittest and private methods

2006-01-20 Thread lemeia
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.

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.

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?

I hope I've made some sense there.

Patrick
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] unittest and private methods

2006-01-20 Thread lemeia
kent 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?
> 
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
> 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.
> > 
> 
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
> 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.
> 
> 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).

Patrick
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor