Wednesday, May 16, 2007

Unit Testing Private Variables and Functions

How do you write unit tests to exercise private functions and check on private variables? For my projects, I have relied on a technique of adding special testing-only methods to my classes. These methods all have names that begin with FTO_ (for testing only). My regular code may not call these functions. Eventually, I'll write a rule that code-checkers can enforce to make sure that these violations of data hiding don't accidentally appear in non-test code.

However, for a long time I've wanted to know if there is a better way to do this. So, I did what most good programmers do--I asked someone who knows testing better than I do. Which meant talking to the ever-kind Jeff Frederick, who is the main committer of the popular CI server Cruise Control (and the head of product development at Agitar).

Jeff contended that the problem is really one of code design. If all methods are short and specific, then it should be possible to test a private variable by probing the method that uses it. Or said another way: if you can't get at the variable to test it, chances are it's buried in too much code. (Extract Method, I have long believed, is the most important refactoring.)

Likewise private methods. Make 'em small, have them do only one thing, and call them from accessible methods.

I've spent a week noodling around with this sound advice. It appeals to me because almost invariably when I refactor code to make it more testable, I find that I've improved it. So far, Jeff is mostly right. I can eliminate most situations by cleaning up code. However, there are a few routines that look intractable. While I work at find a better way to refactor them (a constant quest of mine, actually), I am curious to know how you solve this problem.

5 comments:

  1. I've seen as much done using reflection before. (http://en.wikibooks.org/wiki/Java_Programming/Reflection/Accessing_Private_Features_with_Reflection has some good example code.) I think Jeff is pretty right on, however, that you're in better shape if you can refactor to the point where you don't need testing kluges like reflection.

    ReplyDelete
  2. Corey: Thanks for the note and the link. I've never used reflection for this purpose. I like it but, as you state, it's not as clean as designing the code better--a task that continues to resist my best efforts ;-)

    ReplyDelete
  3. Two very good tools for this purpose is Test Subclasses and moving the previously private part into a method object or strategy.

    The later gives you two benefits, firstly you get very localized tests for that part making it easy to spot trouble areas, and it gives you a good test hook for free to use when testing the containing class's interactions with the strategy via mocks or other test doubles.

    Both incurrs a bit of design overhead but for non trivial cases I've found it to often be worth the effort.

    ReplyDelete
  4. I found this post when searching for the same answer.. I have used an accessor before. This allows you to make an accessor object of the class you want to test in your test class. This object has access to the private variables and methods in your class. I have unfortunatly gorgot exactly how to create the accessor object, hence the googling.. =)

    ReplyDelete
  5. Im trying to solve this issue right now as well. In C++, i could either use a friend class, make the test class inherit from the class im trying to test(private functions are still inacessable).

    ReplyDelete