I have read this post about how to test private methods. I usually do not test them, because I always thought it's faster to test only public methods that will be called from outside the object. Do you test private methods? Should I always test them?
I do not unit test private methods. A private method is an implementation detail that should be hidden to the users of the class. Testing private methods breaks encapsulation.
If I find that the private method is huge or complex or important enough to require its own tests, I just put it in another class and make it public there (Method Object). Then I can easily test the previously-private-but-now-public method that now lives on its own class.
car.drive()
. If I ask some repair shop to change the oil or spark plugs then the car should expose that functionality in order to consistently implement this task. So automechanic should invoke smth like car.changeSparkPlugs(new SparkPlugs())
. –
Natie If I find that the private method [...] require its own tests, I just put it in another class and make it public there
- how do you decide when a method should be made public? If you do this too much, your private implementation becomes a public API and you're essentially writing tests to test private implementation. But if you don't move methods to separate classes, you'll end up having slow E2E tests to test a few lines of change in some private function. How to find the right balance? –
Ipa What is the purpose of testing?
The majority of the answers so far are saying that private methods are implementation details which don't (or at least shouldn't) matter so long as the public interface is well-tested and working. That's absolutely correct if your only purpose for testing is to guarantee that the public interface works.
Personally, my primary use for code tests is to ensure that future code changes don't cause problems and to aid my debugging efforts if they do. I find that testing the private methods just as thoroughly as the public interface (if not more so!) furthers that purpose.
Consider: You have public method A which calls private method B. A and B both make use of method C. C is changed (perhaps by you, perhaps by a vendor), causing A to start failing its tests. Wouldn't it be useful to have tests for B also, even though it's private, so that you know whether the problem is in A's use of C, B's use of C, or both?
Testing private methods also adds value in cases where test coverage of the public interface is incomplete. While this is a situation we generally want to avoid, the efficiency unit testing depends both on the tests finding bugs and the associated development and maintenance costs of those tests. In some cases, the benefits of 100% test coverage may be judged insufficient to warrant the costs of those tests, producing gaps in the public interface's test coverage. In such cases, a well-targeted test of a private method can be a very effective addition to the code base.
testDoSomething()
or testDoSomethingPrivate()
. This makes the test less valuable.. Here's more reasons for testing private #35071: –
Demarcate I tend to follow the advice of Dave Thomas and Andy Hunt in their book Pragmatic Unit Testing:
In general, you don't want to break any encapsulation for the sake of testing (or as Mom used to say, "don't expose your privates!"). Most of the time, you should be able to test a class by exercising its public methods. If there is significant functionality that is hidden behind private or protected access, that might be a warning sign that there's another class in there struggling to get out.
But sometimes I can't stop myself from testing private methods because it gives me that sense of reassurance that I'm building a completely robust program.
I do not like testing private functionality for a couple of reasons. They are as follows (these are the main points for the TLDR people):
- Typically when you're tempted to test a class's private method, it's a design smell.
- You can test them through the public interface (which is how you want to test them, because that's how the client will call/use them). You can get a false sense of security by seeing the green light on all the passing tests for your private methods. It is much better/safer to test edge cases on your private functions through your public interface.
- You risk severe test duplication (tests that look/feel very similar) by testing private methods. This has major consequences when requirements change, as many more tests than necessary will break. It can also put you in a position where it is hard to refactor because of your test suite...which is the ultimate irony, because the test suite is there to help you safely redesign and refactor!
I'll explain each of these with a concrete example. It turns out that 2) and 3) are somewhat intricately connected, so their example is similar, although I consider them separate reasons why you shouldn't test private methods.
There are times testing private methods is appropriate, it's just important to be aware of the downsides listed above. I'm going to go over it in more detail later.
I also go over why TDD is not a valid excuse for testing private methods at the very end.
Refactoring your way out of a bad design
One of the most common (anti)paterns that I see is what Michael Feathers calls an "Iceberg" class (if you don't know who Michael Feathers is, go buy/read his book "Working Effectively with Legacy Code". He is a person worth knowing about if you are a professional software engineer/developer). There are other (anti)patterns that cause this issue to crop up, but this is by far the most common one I've stumbled across. "Iceberg" classes have one public method, and the rest are private (which is why it's tempting to test the private methods). It's called an "Iceberg" class because there is usually a lone public method poking up, but the rest of the functionality is hidden underwater in the form of private methods. It might look something like this:
For example, you might want to test GetNextToken()
by calling it on a string successively and seeing that it returns the expected result. A function like this does warrant a test: that behavior isn't trivial, especially if your tokenizing rules are complex. Let's pretend it's not all that complex, and we just want to rope in tokens delimited by space. So you write a test, maybe it looks something like this (some language agnostic psuedo-code, hopefully the idea is clear):
TEST_THAT(RuleEvaluator, canParseSpaceDelimtedTokens)
{
input_string = "1 2 test bar"
re = RuleEvaluator(input_string);
ASSERT re.GetNextToken() IS "1";
ASSERT re.GetNextToken() IS "2";
ASSERT re.GetNextToken() IS "test";
ASSERT re.GetNextToken() IS "bar";
ASSERT re.HasMoreTokens() IS FALSE;
}
Well, that actually looks pretty nice. We'd want to make sure we maintain this behavior as we make changes. But GetNextToken()
is a private function! So we can't test it like this, because it wont even compile (assuming we are using some language that actually enforces public/private, unlike some scripting languages like Python). But what about changing the RuleEvaluator
class to follow the Single Responsibility Principle (Single Responsibility Principle)? For instance, we seem to have a parser, tokenizer, and evaluator jammed into one class. Wouldn't it be better to just separate those responsibilities? On top of that, if you create a Tokenizer
class, then it's public methods would be HasMoreTokens()
and GetNextTokens()
. The RuleEvaluator
class could have a Tokenizer
object as a member. Now, we can keep the same test as above, except we are testing the Tokenizer
class instead of the RuleEvaluator
class.
Here's what it might look like in UML:
Note that this new design increases modularity, so you could potentially re-use these classes in other parts of your system (before you couldn't, private methods aren't reusable by definition). This is main advantage of breaking the RuleEvaluator down, along with increased understandability/locality.
The test would look extremely similar, except it would actually compile this time since the GetNextToken()
method is now public on the Tokenizer
class:
TEST_THAT(Tokenizer, canParseSpaceDelimtedTokens)
{
input_string = "1 2 test bar"
tokenizer = Tokenizer(input_string);
ASSERT tokenizer.GetNextToken() IS "1";
ASSERT tokenizer.GetNextToken() IS "2";
ASSERT tokenizer.GetNextToken() IS "test";
ASSERT tokenizer.GetNextToken() IS "bar";
ASSERT tokenizer.HasMoreTokens() IS FALSE;
}
Testing private components through a public interface and avoiding test duplication
Even if you don't think you can break your problem down into fewer modular components (which you can 95% of the time if you just try to do it), you can simply test the private functions through a public interface. Many times private members aren't worth testing because they will be tested through the public interface. A lot of times what I see is tests that look very similar, but test two different functions/methods. What ends up happening is that when requirements change (and they always do), you now have 2 broken tests instead of 1. And if you really tested all your private methods, you might have more like 10 broken tests instead of 1. In short, testing private functions (by using FRIEND_TEST
or making them public or using reflection) that could otherwise be tested through a public interface can cause test duplication. You really don't want this, because nothing hurts more than your test suite slowing you down. It's supposed to decrease development time and decrease maintenance costs! If you test private methods that are otherwise tested through a public interface, the test suite may very well do the opposite, and actively increase maintenance costs and increase development time. When you make a private function public, or if you use something like FRIEND_TEST
and/or reflection, you'll usually end up regretting it in the long run.
Consider the following possible implementation of the Tokenizer
class:
Let's say that SplitUpByDelimiter()
is responsible for returning an array such that each element in the array is a token. Furthermore, let's just say that GetNextToken()
is simply an iterator over this vector. So your public test might look this:
TEST_THAT(Tokenizer, canParseSpaceDelimtedTokens)
{
input_string = "1 2 test bar"
tokenizer = Tokenizer(input_string);
ASSERT tokenizer.GetNextToken() IS "1";
ASSERT tokenizer.GetNextToken() IS "2";
ASSERT tokenizer.GetNextToken() IS "test";
ASSERT tokenizer.GetNextToken() IS "bar";
ASSERT tokenizer.HasMoreTokens() IS false;
}
Let's pretend that we have what Michael Feather's calls a groping tool. This is a tool that lets you touch other people's private parts. An example is FRIEND_TEST
from googletest, or reflection if the language supports it.
TEST_THAT(TokenizerTest, canGenerateSpaceDelimtedTokens)
{
input_string = "1 2 test bar"
tokenizer = Tokenizer(input_string);
result_array = tokenizer.SplitUpByDelimiter(" ");
ASSERT result.size() IS 4;
ASSERT result[0] IS "1";
ASSERT result[1] IS "2";
ASSERT result[2] IS "test";
ASSERT result[3] IS "bar";
}
Well, now let's say the requirements change, and the tokenizing becomes much more complex. You decide that a simple string delimiter won't suffice, and you need a Delimiter
class to handle the job. Naturally, you're going to expect one test to break, but that pain increases when you test private functions.
When can testing private methods be appropriate?
There is no "one size fits all" in software. Sometimes it's okay (and actually ideal) to "break the rules". I strongly advocate not testing private functionality when you can. There are two main situations when I think it's okay:
I've worked extensively with legacy systems (which is why I'm such a big Michael Feathers fan), and I can safely say that sometimes it is simply safest to just test the private functionality. It can be especially helpful for getting "characterization tests" into the baseline.
You're in a rush, and have to do the fastest thing possible for here and now. In the long run, you don't want to test private methods. But I will say that it usually takes some time to refactor to address design issues. And sometimes you have to ship in a week. That's okay: do the quick and dirty and test the private methods using a groping tool if that's what you think is the fastest and most reliable way to get the job done. But understand that what you did was suboptimal in the long run, and please consider coming back to it (or, if it was forgotten about but you see it later, fix it).
There are probably other situations where it's okay. If you think it's okay, and you have a good justification, then do it. No one is stopping you. Just be aware of the potential costs.
The TDD Excuse
As an aside, I really don't like people using TDD as an excuse for testing private methods. I practice TDD, and I do not think TDD forces you to do this. You can write your test (for your public interface) first, and then write code to satisfy that interface. Sometimes I write a test for a public interface, and I'll satisfy it by writing one or two smaller private methods as well (but I don't test the private methods directly, but I know they work or my public test would be failing). If I need to test edge cases of that private method, I'll write a whole bunch of tests that will hit them through my public interface. If you can't figure out how to hit the edge cases, this is a strong sign you need to refactor into small components each with their own public methods. It's a sign your private functions are doing too much, and outside the scope of the class.
Also, sometimes I find I write a test that is too big of a bite to chew at the moment, and so I think "eh I'll come back to that test later when I have more of an API to work with" (I'll comment it out and keep it in the back of my mind). This is where a lot of devs I've met will then start writing tests for their private functionality, using TDD as the scapegoat. They say "oh, well I need some other test, but in order to write that test, I'll need these private methods. Therefore, since I can't write any production code without writing a test, I need to write a test for a private method." But what they really need to be doing is refactoring into smaller and reusable components instead of adding/testing a bunch of private methods to their current class.
Note:
I answered a similar question about testing private methods using GoogleTest a little while ago. I've mostly modified that answer to be more language agnostic here.
P.S. Here's the relevant lecture about iceberg classes and groping tools by Michael Feathers: https://www.youtube.com/watch?v=4cVZvoFGJTU
_
, it signals "hey, this is 'private'. You can use it, but full disclosure, it wasn't designed for reuse and you should only use it if you really know what you're doing". You could take the same approach in any language: make those members public, but mark them with a leading _
. Or maybe those functions really should be private, and just tested through a public interface (see answer for more details). It's case by case, no general rule –
Urbane I kind of feel compelled to test private functions as I am following more and more one of our latest QA recommendation in our project:
No more than 10 in cyclomatic complexity per function.
Now the side effect of the enforcing of this policy is that many of my very large public functions get divided in many more focused, better named private function.
The public function still there (of course) but is essentially reduced to called all those private 'sub-functions'
That is actually cool, because the callstack is now much easier to read (instead of a bug within a large function, I have a bug in a sub-sub-function with the name of the previous functions in the callstack to help me to understand 'how I got there')
However, it now seem easier to unit-test directly those private functions, and leave the testing of the large public function to some kind of 'integration' test where a scenario needs to be addressed.
Just my 2 cents.
Yes I do test private functions, because although they are tested by your public methods, it is nice in TDD (Test Driven Design) to test the smallest part of the application. But private functions are not accessible when you are in your test unit class. Here's what we do to test our private methods.
Why do we have private methods?
Private functions mainly exists in our class because we want to create readable code in our public methods. We do not want the user of this class to call these methods directly, but through our public methods. Also, we do not want change their behavior when extending the class (in case of protected), hence it's a private.
When we code, we use test-driven-design (TDD). This means that sometimes we stumble on a piece of functionality that is private and want to test. Private functions are not testable in phpUnit, because we cannot access them in the Test class (they are private).
We think here are 3 solutions:
1. You can test your privates through your public methods
Advantages
- Straightforward unit testing (no 'hacks' needed)
Disadvantages
- Programmer needs to understand the public method, while he only wants to test the private method
- You are not testing the smallest testable part of the application
2. If the private is so important, then maybe it is a codesmell to create a new separate class for it
Advantages
- You can refactor this to a new class, because if it is that important, other classes may need it too
- The testable unit is now a public method, so testable
Disadvantages
- You dont want to create a class if it is not needed, and only used by the class where the method is coming from
- Potential performance loss because of added overhead
3. Change the access modifier to (final) protected
Advantages
- You are testing the smallest testable part of the application. When using final protected, the function will not be overridable (just like a private)
- No performance loss
- No extra overhead
Disadvantages
- You are changing a private access to protected, which means it's accessible by it's children
- You still need a Mock class in your test class to use it
Example
class Detective {
public function investigate() {}
private function sleepWithSuspect($suspect) {}
}
Altered version:
class Detective {
public function investigate() {}
final protected function sleepWithSuspect($suspect) {}
}
In Test class:
class Mock_Detective extends Detective {
public test_sleepWithSuspect($suspect)
{
//this is now accessible, but still not overridable!
$this->sleepWithSuspect($suspect);
}
}
So our test unit can now call test_sleepWithSuspect to test our former private function.
I think it's best to just test the public interface of an object. From the point of view of the outside world, only the behavior of the public interface matters and this is what your unit tests should be directed towards.
Once you have some solid unit tests written for an object you do not want to have to go back and change those tests just because the implementation behind the interface changed. In this situation, you've ruined the consistency of your unit testing.
If your private method is not tested by calling your public methods then what is it doing? I'm talking private not protected or friend.
If the private method is well defined (ie, it has a function that is testable and is not meant to change over time) then yes. I test everything that's testable where it makes sense.
For instance, an encryption library might hide the fact that it performs block encryption with a private method that encrypts only 8 bytes at a time. I would write a unit test for that - it's not meant to change, even though it's hidden, and if it does break (due to future performance enhancements, for instance) then I want to know that it's the private function that broke, not just that one of the public functions broke.
It speeds debugging later.
-Adam
I am not an expert in this field, but unit testing should test behaviour, not implementation. Private methods are strictly part of the implementation, so IMHO should not be tested.
If you are developing test driven (TDD), you will test your private methods.
We test private methods by inference, by which I mean we look for total class test coverage of at least 95%, but only have our tests call into public or internal methods. To get the coverage, we need to make multiple calls to the public/internals based on the different scenarios that may occur. This makes our tests more intentful around the purpose of the code they are testing.
Trumpi's answer to the post you linked is the best one.
Unit tests I believe are for testing public methods. Your public methods use your private methods, so indirectly they are also getting tested.
I've been stewing over this issue for a while especially with trying my hand at TDD.
I've come across two posts that I think address this problem thoroughly enough in the case of TDD.
In Summary:
When using test driven development (design) techniques, private methods should arise only during the re-factoring process of already working and tested code.
By the very nature of the process, any bit of simple implementation functionality extracted out of a thoroughly tested function will be it self tested (i.e. indirect testing coverage).
To me it seems clear enough that in the beginning part of coding most methods will be higher level functions because they are encapsulating/describing the design.
Therefore, these methods will be public and testing them will be easy enough.
The private methods will come later once everything is working well and we are re factoring for the sake of readability and cleanliness.
As quoted above, "If you don't test your private methods, how do you know they won't break?"
This is a major issue. One of the big points of unit tests is to know where, when, and how something broke ASAP. Thus decreasing a significant amount of development & QA effort. If all that is tested is the public, then you don't have honest coverage and delineation of the internals of the class.
I've found one of the best ways to do this is simply add the test reference to the project and put the tests in a class parallel to the private methods. Put in the appropriate build logic so that the tests don't build into the final project.
Then you have all the benefits of having these methods tested and you can find problems in seconds versus minutes or hours.
So in summary, yes, unit test your private methods.
You should not. If your private methods have enough complexity that must be tested, you should put them on another class. Keep high cohesion, a class should have only one purpose. The class public interface should be enough.
I understand the point of view where private methods are considered as implementations details and then don't have to be tested. And I would stick with this rule if we had to develop outside of the object only. But us, are we some kind of restricted developers who are developing only outside of objects, calling only their public methods? Or are we actually also developing that object? As we are not bound to program outside objects, we will probably have to call those private methods into new public ones we are developing. Wouldn't it be great to know that the private method resist against all odds?
I know some people could answer that if we are developing another public method into that object then this one should be tested and that's it (the private method could carry on living without test). But this is also true for any public methods of an object: when developing a web app, all the public methods of an object are called from controllers methods and hence could be considered as implementation details for controllers.
So why are we unit testing objects? Because it is really difficult, not to say impossible to be sure that we are testing the controllers' methods with the appropriate input which will trigger all the branches of the underlying code. In other words, the higher we are in the stack, the more difficult it is to test all the behaviour. And so is the same for private methods.
To me the frontier between private and public methods is a psychologic criteria when it comes to tests. Criteria which matters more to me are:
- is the method called more than once from different places?
- is the method sophisticated enough to require tests?
Yes you should test private methods, wherever possible. Why? To avoid an unnecessary state space explosion of test cases which ultimately just end up implicitly testing the same private functions repeatedly on the same inputs. Let's explain why with an example.
Consider the following slightly contrived example. Suppose we want to expose publicly a function that takes 3 integers and returns true if and only if those 3 integers are all prime. We might implement it like this:
public bool allPrime(int a, int b, int c)
{
return andAll(isPrime(a), isPrime(b), isPrime(c))
}
private bool andAll(bool... boolArray)
{
foreach (bool b in boolArray)
{
if(b == false) return false;
}
return true;
}
private bool isPrime(int x){
//Implementation to go here. Sorry if you were expecting a prime sieve.
}
Now, if we were to take the strict approach that only public functions should be tested, we'd only be allowed to test allPrime
and not isPrime
or andAll
.
As a tester, we might be interested in five possibilities for each argument: < 0
, = 0
, = 1
, prime > 1
, not prime > 1
. But to be thorough, we'd have to also see how every combination of the arguments plays together. So that's 5*5*5
= 125 test cases we'd need to thoroughly test this function, according to our intuitions.
On the other hand, if we were allowed to test the private functions, we could cover as much ground with fewer test cases. We'd need only 5 test cases to test isPrime
to the same level as our previous intuition. And by the small scope hypothesis proposed by Daniel Jackson, we'd only need to test the andAll
function up to a small length e.g. 3 or 4. Which would be at most 16 more tests. So 21 tests in total. Instead of 125. Of course, we probably would want to run a few tests on allPrime
, but we wouldn't feel so obliged to cover exhaustively all 125 combinations of input scenarios we said we cared about. Just a few happy paths.
A contrived example, for sure, but it was necessary for a clear demonstration. And the pattern extends to real software. Private functions are usually the lowest level building blocks, and are thus often combined together to yield higher level logic. Meaning at higher levels, we have more repetitions of the lower level stuff due to the various combinations.
isPrime
are truly independent, so testing every combination blindly is pretty purposeless. Secondly, marking a pure function called isPrime
private violates so many design rules that I don't even know where to get started. isPrime
should very clearly be a public function. That being said, I do get what you're saying regardless of this extremely poor example. However it's built off the premise you'd want to do combination testing, when in real software systems this is rarely a good idea. –
Urbane If you don't test your private methods, how do you know they won't break?
It's obviously language dependent. In the past with c++, I've declared the testing class to be a friend class. Unfortunately, this does require your production code to know about the testing class.
Public vs. private is not a useful distinction for what apis to call from your tests, nor is method vs. class. Most testable units are visible in one context, but hidden in others.
What matters is coverage and costs. You need to minimize costs while achieving coverage goals of your project (line, branch, path, block, method, class, equivalence class, use-case... whatever the team decides).
So use tools to ensure coverage, and design your tests to cause least costs(short and long-term).
Don't make tests more expensive than necessary. If it's cheapest to only test public entry points do that. If it's cheapest to test private methods, do that.
As you get more experienced, you will become better at predicting when it's worth refactoring to avoid long-term costs of test maintenance.
If I find that the private method is huge or complex or important enough to require its own tests, I just put it in another class and make it public there (Method Object). Then I can easily test the previously private but now public method that now lives on its own class.
I never understand the concept of Unit Test but now I know what it's the objective.
A Unit Test is not a complete test. So, it's not a replacement for QA and manual test. The concept of TDD in this aspect is wrong since you can't test everything, including private methods but also, methods that use resources (especially resources that we don't have control). TDD is basing all its quality is something that it could not be achieved.
A Unit test is more a pivot test You mark some arbitrary pivot and the result of pivot should stay the same.
If the method is significant enough/complex enough , I'll usually make it "protected" and test it. Some methods will be left private and tested implicitly as part of unit tests for the public/protected methods.
I see many people are in the same line of thinking: test at the public level. but isn't that what our QA team does? They test input and expected output. If as developers we only test the public methods then we are simply redoing QA's job and not adding any value by "unit testing".
One main point is
If we test to ensure the correctness of the logic, and a private method is carrying a logic, we should test it. Isn't it? So why are we going to skip that?
Writing tests based on the visibility of methods is completely irrelevant idea.
Conversely
On the other hand, calling a private method outside the original class is a main problem. And also there are limitations to mock a private method in some mocking tools. (Ex: Mockito)
Though there are some tools like Power Mock which supports that, it is a dangerous operation. The reason is it needs to hack the JVM to achieve that.
One work around that can be done is (If you want to write test cases for private methods)
Declare those private methods as protected. But it may not be convenient for several situations.
The answer to "Should I test private methods?" is ".......sometimes". Typically you should be testing against the interface of your classes.
- One of the reasons is because you do not need double coverage for a feature.
- Another reason is that if you change private methods, you will have to update each test for them, even if the interface of your object hasn't changed at all.
Here is an example:
class Thing
def some_string
one + two
end
private
def one
'aaaa'
end
def two
'bbbb'
end
end
class RefactoredThing
def some_string
one + one_a + two + two_b
end
private
def one
'aa'
end
def one_a
'aa'
end
def two
'bb'
end
def two_b
'bb'
end
end
In RefactoredThing
you now have 5 tests, 2 of which you had to update for refactoring, but your object's functionality really hasn't changed. So let's say that things are more complex than that and you have some method that defines the order of the output such as:
def some_string_positioner
if some case
elsif other case
elsif other case
elsif other case
else one more case
end
end
This shouldn't be run by an outside user, but your encapsulating class may be to heavy to run that much logic through it over and over again. In this case maybe you would rather extract this into a seperate class, give that class an interface and test against it.
And finally, let's say that your main object is super heavy, and the method is quite small and you really need to ensure that the output is correct. You are thinking, "I have to test this private method!". Have you that maybe you can make your object lighter by passing in some of the heavy work as an initialization parameter? Then you can pass something lighter in and test against that.
No You shouldn't test the Private Methods why? and moreover the popular mocking framework such as Mockito doesn't provide support for testing private methods.
It's not only about public or private methods or functions, it is about implementation details. Private functions are just one aspect of implementation details.
Unit-testing, after all, is a white box testing approach. For example, whoever uses coverage analysis to identify parts of the code that have been neglected in testing so far, goes into the implementation details.
A) Yes, you should be testing implementation details:
Think of a sort function which for performance reasons uses a private implementation of BubbleSort if there are up to 10 elements, and a private implementation of a different sort approach (say, heapsort) if there are more than 10 elements. The public API is that of a sort function. Your test suite, however, better makes use of the knowledge that there are actually two sort algorithms used.
In this example, surely, you could perform the tests on the public API. This would, however, require to have a number of test cases that execute the sort function with more than 10 elements, such that the heapsort algorithm is sufficiently well tested. The existence of such test cases alone is an indication that the test suite is connected to the implementation details of the function.
If the implementation details of the sort function change, maybe in the way that the limit between the two sorting algorithms is shifted or that heapsort is replaced by mergesort or whatever: The existing tests will continue to work. Their value nevertheless is then questionable, and they likely need to be reworked to better test the changed sort function. In other words, there will be a maintenance effort despite the fact that tests were on the public API.
B) How to test implementation details
One reason why many people argue one should not test private functions or implementation details is, that the implementation details are more likely to change. This higher likelyness of change at least is one of the reasons for hiding implementation details behind interfaces.
Now, assume that the implementation behind the interface contains larger private parts for which individual tests on the internal interface might be an option. Some people argue, these parts should not be tested when private, they should be turned into something public. Once public, unit-testing that code would be OK.
This is interesting: While the interface was internal, it was likely to change, being an implementation detail. Taking the same interface, making it public does some magic transformation, namely turning it into an interface that is less likely to change. Obviously there is some flaw in this argumentation.
But, there is nevertheless some truth behind this: When testing implementation details, in particular using internal interfaces, one should strive to use interfaces that are likely to remain stable. Whether some interface is likely to be stable is, however, not simply decidable based on whether it is public or private. In the projects from world I have been working in for some time, public interfaces also often enough change, and many private interfaces have remained untouched for ages.
Still, it is a good rule of thumb to use the "front door first" (see http://xunitpatterns.com/Principles%20of%20Test%20Automation.html). But keep in mind that it is called "front door first" and not "front door only".
C) Summary
Test also the implementation details. Prefer testing on stable interfaces (public or private). If implementation details change, also tests on the public API need to be revised. Turning something private into public does not magically change its stability.
You can also make your method package-private i.e. default and you should be able to unit test it unless it is required to be private.
Absolutely YES. That is the point of Unit testing, you test Units. Private method is a Unit. Without testing private methods TDD (Test Driven Development) would be impossible,
© 2022 - 2024 — McMap. All rights reserved.