Tuesday, September 20, 2005

Private Testing

David Buck and Charles Monteiro have been discussing how to make sure "private" methods in Smalltalk stay "private". Both have great techniques and it of course got me to thinking: "What a great use for unit tests!"

In all Smalltalks, we categorize methods of a class. Why not mark the private methods in some way? For example, use "private" somewhere in the category name (private, private-processing, private-accessing, etc). This way we know what should be private and what shouldn't be. It doesn't matter the convention just pick one. Now, that we know the private methods, create an object proxy that forwards all calls to the real object. This proxy would check if the method coming in is "private" and signal an exception if a method is "private" since only outside objects will call the proxy directly (Everything else will behind the proxy wall). Now, just pass the proxy around in the unit test as if it were the real object. Let the unit tests verify that we are not calling "private" methods and we have no run-time costs. Of course, we could get fancy and use method wrappers and #become:, but I will leave that as an exercise to the reader (or maybe a future blog entry?).

The main point of this post was to give yet another idea of how to make sure private methods stay private. I would love to hear more techniques. This technique that I just described is what I call meta-unit-tests. We are verifying meta-information about our program. I've used meta-unit-tests for making sure deprecated API calls are not sent in my code and that certain methods are implemented (ie don't have super that calls #shouldBeImplemented). We have a lot of information available to us at unit test time. We can take advantage of it!

3 comments:

Anonymous said...

If you have some kind of pragmas or method annotations support, you could put this information in those.

Blaine Buxton said...

YES! This is why I suggested categories, but left it open. Since in Smalltalk, you can get to everything, there is a CompiledMethod object. You can ask all kinds of questions. You could even put #private in your method and look for the literal #private. I know there are extensions to various Smalltalks that add annotations. The Tweak framework in Squeak makes extensive use of annotations. No changes to the language. You just change some code and voila you have annotations. It's great having an extensible language!

Anonymous said...

could get more fanciful - change the compiler to look whether a method is messaging methods in the "private" category
i am a little doubtful though at introducing tthe concept of private versus public in a language like Smalltalk. it is a very static concept and IMHO seems to go against a very basic Smalltalk axiom - trust the developer.
having said that, an external tool (maybe as part of a code critique package ?) which advises on possible inappropriate usage based on category might make sense