Preserving the integrity of private class variables when testing gets handsy

One classic theme in software development is protecting the integrity of your model classes. We lock up access to them by using things like private variables, the proxy pattern, and wrapper classes. Nobody gets to mess with our objects unless they do it our way.

But what about when testing needs to get its hands on restricted parts of our model classes? Imagine that you’ve got a GameBoard class with associated members pieces, bank, and deckCards. Here’s a sample UML to help you visualize:

image
Example UML for a board game.

Let’s examine the PlayingPieces for just a second. As we can see, the GameBoard makes these pieces private, meaning they can’t be freely changed except through the movePiece method. And that method may be pretty restrictive in what it allows – it may only allow so many moves per turn, it may take away resources for moving, etc. And for testers who need to get the model into a certain state, that can be a bit of a nightmare.

This restriction seems bad, but making the private variables public could be disastrous. It could allow for game play that breaks the rules, allows for model corruption, etc. Any good programmer feels involuntary shudders at the idea of making their variables public…it’s just bad programming. So how do you do reasonable testing?

Private -> Protected

As a bit of review, public variables are available for anybody to access and change. A more restricted permission, private, only allows the class itself to read and modify the variable directly. Any outside classes are forbidden access, except through the occasional public method (notice that we can move pieces around, but only through the movePiece method). There’s middle ground, however, with the protected variable. A protected variable allows access to outside classes, but only if those classes are children of the original class. That means a child class that inherits from a parent with protected variables gets to freely access them all!

Let’s update the above UML so we can make a new GameBoardTest class that is allowed to access the private variables in GameBoard.

inherited
Changes made in red

This allows for a very nice compromise, since the tester now gets open access to the private variables (and can set them to whatsoever she pleases). Simultaneously, you haven’t seriously exposed yourself to data corruption or illegal model allowances.

Caution to the approach

Although protected variables seem like they’re just as secure as private, you’re still accepting an increased amount of exposure (although not nearly as great as setting everything public). The risk you run with setting everything to protected is that somebody outside of testing makes a new child class and starts making those illegal access calls.

You can protect yourself from this too, by using a MockObject pattern. The idea to this is the same, except you never set your private variables to protected. Instead, you make your new child class inherit from the GameBoard class and override all the methods, cutting off their access to the real objects inside. For example, a MockGameBoard object might override the movePiece method to access a new data member specific to the MockObject. That way the MockGameBoard can be treated like a GameBoard although it’s lost all its original functionality. Not particularly helpful if you need to test how the GameBoard integrates into the rest of the code.

One thought on “Preserving the integrity of private class variables when testing gets handsy”

  1. Why not make protected access methods that the child can inherit and use, but still restrict some access? Seems like it’d be even safer since you can do asserts and double checks along the way

Leave a Reply

Your email address will not be published. Required fields are marked *