Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is wrong with making a unit test a friend of the class it is testing? [duplicate]

In C++, I have often made a unit test class a friend of the class I am testing. I do this because I sometimes feel the need to write a unit test for a private method, or maybe I want access to some private member so I can more easily setup the state of the object so I can test it. To me this helps preserve encapsulation and abstraction because I am not modifying the public or protected interface of the class.

If I buy a third party library, I wouldn't want its public interface to be polluted with a bunch of public methods I don't need to know about simply because the vendor wanted to unit test!

Nor do I want have to worry about a bunch of protected members that I don't need to know about if I am inheriting from a class.

That is why I say it preserves abstraction and encapsulation.

At my new job they frown against using friend classes even for unit tests. They say because the class should not "know" anything about the tests and that you do not want tight coupling of the class and its test.

Can someone please explain these reasons to me more so that I may understand better? I just do not see why using a friend for unit tests is bad.

like image 355
cchampion Avatar asked Nov 13 '10 06:11

cchampion


People also ask

What is the major disadvantage of unit testing?

Limitations of Unit Testing Unit testing cannot detect integration or interfacing issues between two modules. It cannot catch complex errors in the system ranging from multiple modules. It cannot test non-functional attributes like usability, scalability, the overall performance of the system, etc.

What errors are commonly found during unit testing?

Unit testing considerations What errors are commonly found during Unit Testing? (1) Misunderstood or incorrect arithmetic precedence, (2) Mixed mode operations, (3) Incorrect initialization, (4) Precision inaccuracy, (5) Incorrect symbolic representation of an expression.

What makes a good unit test?

Unit testing guidelines demand that a good unit test should be independent, repeatable, readable, exhaustive, realistic, maintainable, fast and easy. These are the best practices you want to keep in mind in order to write effective unit tests and make sure the time invested is truly useful.


2 Answers

Ideally, you shouldn't need to unit test private methods at all. All a consumer of your class should care about is the public interface, so that's what you should test. If a private method has a bug, it should be caught by a unit test that invokes some public method on the class which eventually ends up calling the buggy private method. If a bug manages to slip by, this indicates that your test cases don't fully reflect the contract you wish your class to implement. The solution to this problem is almost certainly to test public methods with more scrutiny, not to have your test cases dig into the class's implementation details.

Again, this is the ideal case. In the real world, things may not always be so clear, and having a unit testing class be a friend of the class it tests might be acceptable, or even desirable. Still, it's probably not something you want to do all the time. If it seems to come up often enough, that might a sign that your classes are too large and/or performing too many tasks. If so, further subdividing them by refactoring complex sets of private methods into separate classes should help remove the need for unit tests to know about implementation details.

like image 91
bcat Avatar answered Oct 16 '22 11:10

bcat


You should consider that there are different styles and methods to test: Black box testing only tests the public interface (treating the class as a black box). If you have an abstract base class you can even use the same tests against all your implementations.

If you use White box testing, you might even look at the details of the implementation. Not only about which private methods a class has, but what kind of conditional statements are included (i.e. if you want to increase your condition coverage because you know that the conditions were hard to code). In white box testing, you definitely have "high coupling" between classes/implementation and the tests which is necessary because you want to test the implementation and not the interface.

As bcat pointed out, it's often helpful to use composition and more but smaller classes instead of many private methods. This simplifies white box testing because you can more easily specify the test cases to get a good test coverage.

like image 15
Philipp Avatar answered Oct 16 '22 11:10

Philipp