Jason in a Nutshell

All about programming and whatever else comes to mind

Enemies of Test Driven Development part I: encapsulation

Posted by Jason Baker on January 8, 2009

Before you leave a nasty comment below hear me out. I’m not saying that we need to abandon the idea of encapsulation.  That would be stupid.  Rather, I’m saying that to be able to do test driven development properly, you need to re-think how you handle encapsulation.

(I had thought of naming this post “Enemies of Test Driven Development part I:  The Ideas You Currently Have About Encapsulation”, but that was too long)

What’s that smell?

The most difficult part of dealing with Test Driven Development is learning how to test private methods.  The answer to that is simpler than you may think:  you don’t.

Here’s a quote from Michael Feathers (one of the gurus of testing):

It seems that reverse is true also.  Classes which are hard to instantiate and use in a test harness are more coupled than they could be, and classes with private methods that you feel the urge to test, invariably have some sort of cohesion problem: they have more than one responsibility.

All I can say is that in the community of people doing test-driven development there are a number of people who have found that this question of testing private methods doesn’t come up much in their practice.  They target both testability and good design and find that both goals nurture each other.

It seems to me that Feathers is stopping just short of calling private methods code smells.  I’m going to take it there:  private methods are a code smell.  Does this mean that every private method that’s ever been written is bad?  Of course not.  There are times when private methods are a good and wholesome thing.  But if you’re using a private method, you should really consider if your design is a good one.

Solutions

I won’t dwell much on why private methods can be indicative of bad code.  Plenty has been written on that already.  Rather, I want to focus on overcoming these challenges.  So I’ve come up with a list of solutions to this problem.  Keep in mind that these solutions are tools for the toolbox.  They may not be applicable in every situation, nor are they a complete list.

With that said, here are some possible solutions:

Make it public!

What is it? This is probably the simplest way to overcome the problem of untestability.  And in my opinion, it’s the best solution for the TDD newbie.  Why?  Nine times out of ten, it’s a result of doing what you’re told.  If your university is/was like mine, you were told to make everything private unless you had good reason to make it public.  While that is actually true, it’s not really very useful.  There’s a reason for that:  testability is a perfectly good reason to make something public.  And you should test most of your code.

How do I do it? It’s simple, suppose I want to test SomeMethod:


class SomeClass
{
    private void SomeMethod() {...}
}

I could do this:

class SomeClass
{
    public void SomeMethod() {...}
}

Simple, eh?

When should I use it? To decide if this is the avenue you should take, evaluate why you want to make the method private.  If this is just a case of not wanting to make it public because you want to simplify the class’s API, there’s a good chance you’re over-hiding and you should evaluate this solution.  If there’s a deeper reason why you don’t want to make it public, there are a few other solutions.

Use Conventions

What is it? Python’s gotten by on this method for a long time.  And it works pretty well.  The idea is that “we’re all adults here” (if anybody can tell me who to attribute that quote to, let me know!).  If you don’t want somebody to call a certain method, name it as such.  In Python, the convention is to prefix private methods with a single underscore.

C++, C#, and Java users will probably disagree with me here (and that’s fine), but I think that this is an important tactic to note.

How do I do it? Simple.  Suppose I want to test SomeMethod:

class SomeClass(object):
    def SomeMethod(self):
        ...

Then I would just do this:

class SomeClass(object):
    def _someMethod(self):
        ...

When should I use it? The most obvious case is if you’re in an environment where this is acceptable.  If you’re in a Python shop, chances are you’re ok with this.  If you’re in a “curly brace” shop, you may have problems doing this.  We can dispute whether or not the reasons for that are good, but that’s really not relevant.  If you’re in such an organization, you should probably try something else if only for no other reason than to not hear co-workers complain.

Access Denied!

What is it? Just because you aren’t making private methods doesn’t mean you can’t disallow their use.  This is where interfaces and abstract base classes come into play (for the sake of succinctness, I’ll use the word “interface” to refer to both of these unless otherwise noted for the rest of the post).  Don’t want to allow client code to access a certain method, don’t put it in the interface!  Granted, this isn’t a perfect way to prevent client code from calling a method.  But then again, neither is making the method private (even in C++, although it isn’t easy to break there).

Be careful here though, if you find yourself creating too many interfaces to allow for giving different classes access to different areas, you’re probably creating a God Object.

How do I do it? Suppose I have a class SomeClass and I want to expose everything but SomeMethod:

class SomeClass
{
    public void SomeMethod() {...}
    public void SomeOtherMethod() {...}
    public void SomeOtherOtherMethod() {...}
}

I could just create an interface ISomeClass:

interface ISomeClass
{
    public void SomeOtherMethod() {...}
    public void SomeOtherOtherMethod() {...}
}

When should I use it? If you’re working in a C++/C#/Java shop.  This is a good alternative to the “conventions” method noted above.

Using Inheritance

What is it? If you’re willing to make a method protected, you can test it by inheriting from the class and exposing a public method that calls the method.

How do I do it? Suppose you want to test SomeMethod:

class SomeClass
{
    private void SomeMethod() {...}
}

You can then do this:

class SomeDerivedClass
{
    public void SomeMethod2() {SomeMethod();}
}

When should I use it? If you’re working with legacy code, this may be your only option.  Typically this works best when you want to test a class that you don’t have the luxury of being able to change.  Keep in mind that you’re adding another layer between your code and your tests, though.  This is a bigger deal in some languages than it is in others, but in general it’s to be avoided if at all possible.

Make Another Class

What is it? Ok, so you’ve reviewed the above methods, and you’re still just not comfortable with making them public.  This is usually an indicator that your class is doing too much.  Not only does this make testing difficult, it results in more tightly coupled code that will turn into a maintenence nightmare.  The idea then, is to separate the extra functionality into a separate class.

How do I do it? Suppose I have a class to access a database that looks something like this:

class UserParser(object):
    def _fillInfo(self):
        self.Username = getUnameFromDB()
        self.EmailAddress = getEmailFromDB()
        self.Name = getNameFromDB()
    def ParseData(self):
        _fillInfo()
        do_stuff_with_filled_data()

I can do this:

class UserAccessor(object):
    def FillInfo(self):
        self.Username = getUnameFromDB()
        self.EmailAddress = getEmailFromDB()
        self.Name = getNameFromDB()

class UserParser(object):
    def __init__(self):
        self.user = UserAccessor()
    def ParseData(self):
        self.user.FillInfo()
        do_stuff_with_filled_data(self.user)

When should I use it? There are a couple of situations when you would use this:

  1. When you can’t or won’t use any of the other methods.
  2. When you have a significant amount of methods you need to test but don’t want to make public.

Conclusion

Wow, this post ended up being longer than I thought!  I’m sure that there are a lot of techniques for doing this, and I’m sure that I’m missing some stuff.  So let me know them in the comments.

Update

Thanks to Przemek Owczarek for pointing out another method!

Other Posts

About these ads

4 Responses to “Enemies of Test Driven Development part I: encapsulation”

  1. Przemek Owczarek said

    Good stuff. How about inheriting from a class and making a public method that calls a private method we want to test? Simple forward call. I use it very often when I just can’t change a class I want to test.

    Regards,
    Przemek

  2. Jason Baker said

    An excellent point (that I’m not sure why I missed). I’ll see if I can add that in when I get a chance.

  3. [...] of Test Driven Development part II: YAGNI Just like in this post’s predecessor, don’t take the title of this post to mean that YAGNI should be abandoned.  YAGNI is still a [...]

  4. Garry said

    Great article. As a pretty much newbie to tdd and unit testing, I have found using inheritance a good tactic to testing privates in non tdd code. I hope in future projects to adopt tdd from the outset which may give me more options.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
Follow

Get every new post delivered to your Inbox.

%d bloggers like this: