When to unit test private methods?

in TDD you are often confronted with the question “should I restrict my unit test to public methods or include private ones as well?”.

There isn’t a widely accepted consensus and there are many articles around on the subject. I’ve been thinking about it recently and this is my take on it.

A class’ public interface is a contract between the class and its users. When you test a class’ public interface you are trying to ensure that it respects the terms of the contract. So testing a public interface is technically enough to ensure that your program is correct (within the scope of unit testing of course, not in a general sense).

Generally nobody cares how your class is internally implemented as long as it works as advertised. Private members are an implementation detail and are used by public members anyways (otherwise you could just delete them), so tests on the public interface cover private members as well.

However, tests on private methods have a benefit: they can help you spot errors closer to where they are originated. You can see it this way: tests on public methods tell you that something went wrong, while tests on private methods can tell you where something went wrong. In other words they bring some comfort.

While additional comfort is nice to have, it always comes at a cost. These are the main costs you’ll assume when deciding to test private members:

  • You’ll have to write more tests.
  • Maintenance becomes quite stressful as you’ll be changing/adding/removing several tests every time you make a change in a class implementation.
  • You miss the benefits of LDD (Laziness-Driven Development –invented by myself, don’t bother looking in wikipedia). In short, if a developer must write tests for public members only, she will keep them private unless really necessary, just because it takes less work. And keeping the public interface as narrow as possible is a good thing.

In order to answer the original question you’ll have to decide if the benefits are greater than the costs.

Personally, I only test public members and occasionally make an exception for private members that produce values difficult to verify at a glance.

When you combine the output of methods that produce “obvious values” it’s generally easy to spot what went wrong (a null reference, an incompletely initialized object, a wrongly formatted string, etc.). On the other hand, when methods generate for ex. floating point values, it’s difficult to quickly tell if something is wrong, thus it’s difficult to understand what caused a test to fail.

For example, I have a public GetPlexoidMass() function that computes the mass of a plexoid using a complex formula based on sine and cosine*. It made sense for me to test the private Sin and Cos functions as well, so that when a test for GetPlexoidMass turns red it takes me less time to figure out what caused the error without debugging every single step in the formula. The intermediate results inside GetPlexoidMass are floating point numbers and it’s otherwise difficult to understand which one is wrong without an accurate and time-consuming analysis.

This is a case you often find in number manipulation and/or mathematical-intensive libraries, usually found at an application’s core. This kind of function is harder to find the more you move towards the application surface. I would go as far as saying that feeling the constant need to test private members near the application surface may be a code smell and could indicate a problem in the application layering.

I hope these elements may help you make the right choice. If you have other criteria or considerations please let discuss in the comments!

 

* dummy example of course

Silverlight unit testing with NUnit: yes you can (without hacks)!

It may be obvious for most of you, but it took a while to my caveman brain to realize this, so I figured I could post it for other cavemen. You (we) have got an excuse though: the short release cycle of Silverlight means that most stackoverflow questions and blog posts on the subject are out-of-date and refer to older versions of Silverlight (<=3) when what I describe was not possible.

Up to Silverlight 3 you had to use a Silverlight-specific unit testing tool, like the Silverlight Toolkit framework. These tools are quite awesome and have been fundamental, but it’s nice to have the full power of NUnit (or xUnit & co.) at disposal. In addition to the community and tooling support, it’s practical to use the same tool you already use for other .NET projects.

The game changer is called binary assembly compatibility, brought by Silverlight 4. In a few words this means that you can add a reference to a Silverlight assembly from a “full” .NET project (provided that you don’t use any Silverlight-only class).

If your application is correctly layered (for ex. with MVVM) in most cases it’s trivial to keep views and viewModels/models in separate assemblies. ViewModels and models usually don’t reference any Silverlight-only class (otherwise you may have a code smell!) and are 100% compatible with .NET, so testing them with NUnit is as easy as

  • create a .NET class library in your solution
  • add a reference to NUnit (NuGet it!)
  • add a reference to your model and/or viewModel assemblies
  • write your unit tests
  • run them with NUnit

no tweaking or hacking required and works fine with F# assemblies as well.

It is typical for views to use Silverlight-only classes, but this is generally not a problem because it doesn’t make much sense to unit-test them anyways as they are mostly XAML with very little amounts of code-behind.

Free tip: if you want to test internal classes and methods you can add the InternalsVisibleTo attribute to the target assembly.

Happy testing!

bear