This is actually language agnostic. But I'll give you context in python.
I have this parent class
class Mammal(object): def __init__(self): """ do some work """ def eat(self, food): """Eat the food""" way_to_eat = self._eating_method() self._consume(food) def _eating_method(self): """Template method""" def _consume(self, food): """Template method"""
Here eat
is the only public method whereas _consume
and _eating_method
are actually protected methods which will be implemented by child classes.
What will you test when you have written only the Mammal
class?
Obviously all 4 methods.
Now let's introduce a child
class Tiger(Mammal): def _eating_method(self): """Template method""" def _consume(self, food): """Template method"""
Look at this class. It has only 2 protected methods.
Should I test all 4 methods of Tiger
(including 2 inherited) or just test the changes introduced (only overrided 2 methods)?
What is the ideal case?
Unit Tests Should Only Test Public Methods The short answer is that you shouldn't test private methods directly, but only their effects on the public methods that call them. Unit tests are clients of the object under test, much like the other classes in the code that are dependent on the object.
The easiest way would be to make sure your tests are in the same package hierarchy as the class you are testing. If that's not possible then you can subclass the original class and create a public accessor that calls the protected method.
So whether you are using JUnit or SuiteRunner, you have the same four basic approaches to testing private methods: Don't test private methods. Give the methods package access. Use a nested test class.
The answer to the more general question is yes, you should unit test everything you can. Doing so creates a legacy for later so changes down the road can be done with peace of mind. It ensures that your code works as expected.
From a theoretical point of view, you only need to test public methods of your instantiable classes (in standard OOP languages). There is no point in testing the internal behaviour because all you want is "which output for that input" (for a particular method, or for the entire class). You should try to respect it as much as you can because it forces you to ask some questions about the encapsulation of your class and the provided interface which may be decisive for your architecture.
From a pragmatic point of view, you can sometimes have some abstract helper classes with no implemented concrete subclass or an abstract class factoring 90+% of its child classes and where it would be too hard to test the output without plugging into a protected method. In those kinds of cases, you can mock a subclass.
In your straightforward example, I would suggest you to only test the class Tiger
(and only the public method eat
).
Just a note for people thinking to TDD. In TDD, you shouldn't have started to code the class
Mammal
before the classTiger
becauseMammal
should be the result of a refactoring phase. So, you certainly woudn't have any specific test forMammal
.
The way I would approach this is:
Mammal
which provides minimal implementations of the two protected methods that allow you to unit test the behavior of the public methods.Mammal
, but are asserting the behavior that is specific to that subclass.This should give you the necessary testing coverage with a minimal number of tests.
One alternative approach would be to test the subclasses only, and on one of the subclass unit tests also assert the features specific to Mammal
. This avoids the need to create a specific testing subclass, however two disadvantages are:
Mammal
in isolation, and therefore the tests on the Mammal
specific code are susceptible to failing because of issues in the subclass.Mammal
are being tested.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With