I like unit testing, it is proving its worth immensely for the last year and a half or so ive used it. However I always have a problem or rather a niggle with private methods (and protected).
I don't want to make them public or use internals visible to attribute. I want a clean and crisp solution - that is testable and i'd be proud to let someone else look at.
I am coming to the conclusion that if a private method really needs testing independantly then maybe it should be moved out onto another interface and use association to expose the functionality to the calling method. I believe this in essence to be the Facade pattern.
Is this really the best way to go about this?
Or more objectively ... are there any other approaches I have totally overlooked?
Edit: Are we talking about a specific language?
I am working in C#. I had kept code out of the question as i was looking for something abstract. Coming back to it today i realise that is perhaps folly due to languages really being that different.
So some code:
public class CopmlexClass
{
public void SomeMethod()
{ }
private void workerMethod()
{ }
}
would get re factored into
public class CopmlexClass
{
public void SomeMethod()
{ }
public IComplexClassWorker Worker { get; set; }
}
public interface IComplexClassWorker
{
void WorkerMethod();
}
In fact id probably prefer to use constructor injection and not even expose the property
My question is: is that the best way? what are the alternatives bar reflection / internals visible to attribute?
A private method which needs to be tested independently can be the result of the following:
your class is doing too much - its public methods implement functionality which is too complex to be unit tested as a whole, and/or
the effects of calling the specific private method can't be directly sensed from outside the class.
Both cases are usually a clear call to extract another class containing some private method(s) of the original class, turned into public, thus made directly testable. (The sometimes challenging part is to find logically cohesive chunks of functionality which can form useful classes on their own right. You may not always get a perfect result at first - in refactoring, sometimes one needs to make a compromise, a small step into some not-yet-clearly-defined direction. In the long term, such a step may open up new possibilities, call attention to other similar code parts, or the new class may start to attract code bits from other places, eventually forming a coherent class. Or turning into something completely new, but better than what you originally envisioned.)
Exposing the private method via another interface / facade is IMO not going to solve the problem in the long term, only muddles the waters. Classes should have a well defined, complete and minimal interface. Exposing private methods in any way may open up ways to compromise the internal state of the object, which is a Bad Thing.
When we started writing unit tests in our team a couple of years ago we started with the rules you set out above - i.e. we test the public interface of an assembly.
We expected one advantage to be in detecting unreachable code. If the code coverage tools detect code blocks which not being tested, then either tests are missing or the code is unreachable and should be removed.
But in practice we haven't stuck to them. We have a very modular design - more than 30 projects in our main solution (most having a matching unit tests project). We now usually give the test project access to the internals of the project under test.
I think one problem is that we are not automatically using code coverage to detect missing tests or unreachable code. Because this is a manual process, it doesn't get done.
Related
My colleagues and I are currently introducing unit tests to our legacy Java EE5 codebase. We use mostly JUnit and Mockito. In the process of writing tests, we have noticed that several methods in our EJBs were hard to test because they did a lot of things at once.
I'm fairly new to the whole testing business, and so I'm looking for insight in how to better structure the code or the tests. My goal is to write good tests without a headache.
This is an example of one of our methods and its logical steps in a service that manages a message queue:
consumeMessages
acknowledgePreviouslyDownloadedMessages
getNewUnreadMessages
addExtraMessages (depending on somewhat complex conditions)
markMessagesAsDownloaded
serializeMessageObjects
The top-level method is currently exposed in the interface, while all sub-methods are private. As far as I understand it, it would be bad practice to just start testing private methods, as only the public interface should matter.
My first reaction was to just make all the sub-methods public and test them in isolation, then in the top-level method just make sure that it calls the sub-methods. But then a colleague mentioned that it might not be a good idea to expose all those low-level methods at the same level as the other one, as it might cause confusion and other developers might start using when they should be using the top-level one. I can't fault his argument.
So here I am.
How do you reconcile exposing easily testable low-level methods versus avoiding to clutter the interfaces? In our case, the EJB interfaces.
I've read in other unit test questions that one should use dependency injection or follow the single responsibility principle, but I'm having trouble applying it in practice. Would anyone have pointers on how to apply that kind of pattern to the example method above?
Would you recommend other general OO patterns or Java EE patterns?
At first glance, I would say that we probably need to introduce a new class, which would 1) expose public methods that can be unit tested but 2) not be exposed in the public interface of your API.
As an example, let's imagine that you are designing an API for a car. To implement the API, you will need an engine (with complex behavior). You want to fully test your engine, but you don't want to expose details to the clients of the car API (all I know about my car is how to push the start button and how to switch the radio channel).
In that case, what I would do is something like that:
public class Engine {
public void doActionOnEngine() {}
public void doOtherActionOnEngine() {}
}
public class Car {
private Engine engine;
// the setter is used for dependency injection
public void setEngine(Engine engine) {
this.engine = engine;
}
// notice that there is no getter for engine
public void doActionOnCar() {
engine.doActionOnEngine();
}
public void doOtherActionOnCar() {
engine.doActionOnEngine();
engine.doOtherActionOnEngine(),
}
}
For the people using the Car API, there is no way to access the engine directly, so there is no risk to do harm. On the other hand, it is possible to fully unit test the engine.
Dependency Injection (DI) and Single Responsibility Principle (SRP) are highly related.
SRP is basicly stating that each class should only do one thing and delegate all other matters to separate classes. For instance, your serializeMessageObjects method should be extracted into its own class -- let's call it MessageObjectSerializer.
DI means injecting (passing) the MessageObjectSerializer object as an argument to your MessageQueue object -- either in the constructor or in the call to the consumeMessages method. You can use DI frameworks to do this for, but I recommend to do it manually, to get the concept.
Now, if you create an interface for the MessageObjectSerializer, you can pass that to the MessageQueue, and then you get the full value of the pattern, as you can create mocks/stubs for easy testing. Suddenly, consumeMessages doesn't have to pay attention to how serializeMessageObjects behaves.
Below, I have tried to illustrate the pattern. Note, that when you want to test consumeMessages, you don't have to use the the MessageObjectSerializer object. You can make a mock or stub, that does exactly what you want it to do, and pass it instead of the concrete class. This really makes testing so much easier. Please, forgive syntax errors. I did not have access to Visual Studio, so it is written in a text editor.
// THE MAIN CLASS
public class MyMessageQueue()
{
IMessageObjectSerializer _serializer;
//Constructor that takes the gets the serialization logic injected
public MyMessageQueue(IMessageObjectSerializer serializer)
{
_serializer = serializer;
//Also a lot of other injection
}
//Your main method. Now it calls an external object to serialize
public void consumeMessages()
{
//Do all the other stuff
_serializer.serializeMessageObjects()
}
}
//THE SERIALIZER CLASS
Public class MessageObjectSerializer : IMessageObjectSerializer
{
public List<MessageObject> serializeMessageObjects()
{
//DO THE SERILIZATION LOGIC HERE
}
}
//THE INTERFACE FOR THE SERIALIZER
Public interface MessageObjectSerializer
{
List<MessageObject> serializeMessageObjects();
}
EDIT: Sorry, my example is in C#. I hope you can use it anyway :-)
Well, as you have noticed, it's very hard to unit test a concrete, high-level program. You have also identified the two most common issues:
Usually the program is configured to use specific resources, such as a specific file, IP address, hostname etc. To counter this, you need to refactor the program to use dependency injection. This is usually done by adding parameters to the constructor that replace the ahrdcoded values.
It's also very hard to test large classes and methods. This is usually due to the combinatorical explosion in the number of tests required to test a complex piece of logic. To counter this, you will usually refactor first to get lots more (but shorter) methods, then trying to make the code more generic and testable by extracting several classes from your original class that each have a single entry method (public) and several utility methods (private). This is essentially the single responsibility principle.
Now you can start working your way "up" by testing the new classes. This will be a lot easier, as the combinatoricals are much easier to handle at this point.
At some point along the way you will probably find that you can simplify your code greatly by using these design patterns: Command, Composite, Adaptor, Factory, Builder and Facade. These are the most common patterns that cut down on clutter.
Some parts of the old program will probably be largely untestable, either because they are just too crufty, or because it's not worth the trouble. Here you can settle for a simple test that just checks that the output from known input has not changed. Essentially a regression test.
I am very sorry if this question seems stupid, i am a newbie to TCL and TCLtest, I am trying to perform unit test on a few TCLOO programs, and i am having difficulties testing the private methods ( the methods called using keyword 'my' ). Guidance needed
Leaving aside the question of whether you should test private methods, you can get at the methods by one of these schemes:
Use [info object namespace $inst]::my $methodname to call it, which takes advantage of the fact that you can use introspection to find out the real name of my (and that's guaranteed to work; it's needed for when you're doing callbacks with commands like vwait, trace, and Tk's bind).
Use oo::objdefine $inst export $methodname to make the method public for the particular instance. At that point, you can just do $inst $methodname as normal.
Consequence: You should not use a TclOO object's private methods for things that have to be protected heavily (by contrast with, say, a private field in a Java object). The correct level for handling such shrouding of information is either to put it in a master interpreter (with the untrusted code evaluating in a safe slave) or to keep the protected information at the underlying implementation (i.e., C) level. The best option of those two depends on the details of your program; it's usually pretty obvious which is the right choice (you don't write C just for this if you're otherwise just writing Tcl code).
This might look like OT, but bear with me.
Are you sure you have to test private methods? That sounds like testing the implementantion, and thats something you shouldnt do. You should be testing the behavior of your class, and that is tested through its public methods.
If you have a complicated chunk of code in one of the private methods, and you feel it needs to be tested spearately, consider refactoring the code into two separate classes. Make the method that needs testing public in one of the two classes.
That way you avoid having a "god class" that does everything and you get to test what you wanted to test. You might want to read more about Single Responsibility Principle.
If you need specific book titles on refactoring, id recommend "Clean Code" by Robert C. Martin. I love that book!
I am wondering if unit testing private methods is a good practice?
Normally only public interface should be tested.
However, I have found out that during complex calculation, which calls tons of different private methods, it is easier to unit test the private methods first, and then make a simple test for the public interface method.
As an example let's say you have an audio player and you have functions:
void play(){ ... }
void pause(){ ... }
void seek(time t)
{
//All Private methods
checkIfValidTimeRange(...);
moveToFilePos(...);
fillBuffers(...);
}
Normally I would write unit tests for : checkIfValidTimeRange(...), moveToFilePos(...), fillBuffers(...).
But I am not sure if doing so is good practice.
It's not a good practice (yet that doesn't mean you should never do that), and if possible you want to avoid it. Testing private method usually means your design could be better. Let's take a quick look at your player example:
moveToFilePos: sounds more like a responsibility of something doing I\O operations, not a music player's
fillBuffers: more of a memory manager's job rather than music player
checkIfValidTimeRange: again, probably could be moved out of player's scope to some simple validation class (seems like this one might be useful in other places aswell)
At the moment your music player does I/O, memory management and what not else. Is that all really in scope of its responsibilities?
If your private methods are complex enough to warrant testing, you're likely missing some classes where those private methods are turned public.
You certainly can test private methods, but you should take the need to do it as a hint there's something wrong in your design.
IMHO it's a very good idea, I do it all the times. I usually create a helper class which makes the private methods accessable and test it..
Usually it's even easier to test private methods, since they do something very specific. On the other hand you might have a big public method which is a bit harder to test. So it certainly simplifies unit tests.
Which part of your code base is your private methods relying on ?
If somebody changes the way one of the method you are relying on works and thus breaks your method, isn't it worth knowing it ?
Testing is not only for checking that your method behaves as it should, but also to check that changes in other parts of the codebase doesn't break your method.
So unless your method is only using basic constructs of your language, test it !
This question already has answers here:
How do I test a class that has private methods, fields or inner classes?
(58 answers)
Closed 5 years ago.
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.
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.
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.
I feel that Bcat gave a very good answer, but I would like to expound on the exceptional case that he alludes to
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.
I work in a company with a large legacy codebase, which has two problems both of which contribute to making a friend unit-test desirable.
We suffer from obscenely large functions and classes which require refactoring, but in order to refactor it is helpful to have tests.
Much of our code is dependent on database access, which for various reasons should not be brought into the unit tests.
In some cases Mocking is useful to alleviate the latter problem, but very often this just leads to uneccessarily complex design (class heirarchies where none would otherwise be needed), while one could very simply refactor the code in the following way:
class Foo{
public:
some_db_accessing_method(){
// some line(s) of code with db dependance.
// a bunch of code which is the real meat of the function
// maybe a little more db access.
}
}
Now we have the situation where the meat of the function needs refactoring, so we'd like a unit test. It shouldn't be exposed publicly. Now, there's a wonderful technique called mocking that could be used in this situation, but the fact is that in this case a mock is overkill. It would require me to increase the complexity of the design with an unecessary hierarchy.
A far more pragmatic approach would be to do something like this:
class Foo{
public:
some_db_accessing_method(){
// db code as before
unit_testable_meat(data_we_got_from_db);
// maybe more db code.
}
private:
unit_testable_meat(...);
}
The latter gives me all of the benefits I need from unit testing, including giving me that precious safety net to catch errors produced when I refactor the code in the meat. In order to unit test it, I have to friend a UnitTest class, but I would strongly argue that this is is far better than an otherwise useless code heirarchy just to allow me to use a Mock.
I think this should become an idiom, and I think it's a suitable, pragmatic solution to increase the ROI of unit testing.
Like bcat suggested, as much as possible, you need to find bugs using public interface itself. But if you want to do things like printing private variables and comparing with expected result etc(Helpful for developers to debug the issues easily), then you can make UnitTest class as friend to class to be tested. But you may need to add it under a macro like below.
class Myclass
{
#if defined(UNIT_TEST)
friend class UnitTest;
#endif
};
Enable flag UNIT_TEST only when Unit testing is required.
For other releases, you need to disable this flag.
I don't see anything wrong with using a friend unit testing class in many cases. Yes, decomposing a large class into smaller ones is sometimes a better way to go. I think people are a bit too hasty to dismiss using the friend keyword for something like this - it might not be ideal object oriented design, but I can sacrifice a little idealism for better test coverage if that's what I really need.
Typically you only test the public interface so that you are free to redesign and refactor the implementation. Adding test cases for private members defines a requirement and restriction on the implementation of your class.
Make the functions you want to test protected.
Now in your unit test file, create a derived class.
Create public wrapper functions that call your the class-under-test protected functions.
There is one aspect of TDD which I never fully understood.
Suppose somebody asked you to implement a simple Stack object. If you've done your design properly, you will come to a very minimal and clean API. Suppose: push(), pop() and isEmpty(). Anything more than that is over-killing the demand, and allowing the user too much room to mess with your code.
So now let's suppose you want to unit test your code. How do you go about doing this if all your public methods are just the three shown above? Those methods will take your testing only so far.
So either you add private methods, which do not help you at all since they are not visible to your unit test case. Or you make those methods public and there goes your minimalistic API which you worked on so hard. Now the user is going to mess with your Stack and the bugs will be sure to come.
How do you handle this dilemma of opening public methods for testing vs. a clean and simple API?
Edit: just to point in the right direction, It would be nice to get technical pointers (such as "use this hack to expose private methods", etc...) but I am much more intrested in more generic answers as to what of the two concepts is more important, and how you approach this subject.
test the features; this usually means testing the public interface - for should not all features be accessible via the public interface? if they aren't, then they aren't features! There may be exceptions to this, but i can't think of any.
test the public interface; any methods that are not called directly or indirectly from the public interface are not necessary. Not only do they not need to be tested, they do not need to exist at all.
You should take a look at that question : do you test private method?.
To not break the encapsulation, 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 it's own class.
Using your Stack example, you really shouldn't need to expose any inner workings to unit test it. Reiterating what others have said, you should feel free to have as many private methods as needed, but only test through your public API.
[Test]
public void new_instance_should_be_empty()
{
var stack = new Stack();
Assert.That(stack.IsEmpty(), Is.True);
}
[Test]
public void single_push_makes_IsEmpty_false()
{
var stack = new Stack();
stack.Push("first");
Assert.That(stack.IsEmpty(), Is.False);
}
Using a combination of pushing and popping you can simulate all behaviour of the Stack class, because that's the only way a user has to interact with it. You don't need any tricks because you should only be testing what others can use.
[Test]
public void three_pushes_and_three_pops_results_in_empty_stack()
{
var stack = new Stack();
stack.Push("one");
stack.Push("two");
stack.Push("three");
stack.Pop();
stack.Pop();
stack.Pop();
Assert.That(stack.IsEmpty(), Is.True);
}
Sometimes I make methods which would otherwise be private into package level (Java) or internal (.NET) methods, usually with a comment or an annotation/attribute to explain why.
Most of the time, however, I avoid doing this. What would the public API not let you test in your stack case? If the user can see the bug and they're only using the public API, what's stopping you from making the same calls?
The times I expose otherwise-private methods is when it makes it easier to test one part of a complicated set of steps in isolation - if a single method call is very "chunky" it can be very helpful to test each step in isolation, even though the steps shouldn't be visible to a normal user.
right TDD is all about testing behavior which could be tested by public interface... if there are are any private methods then those methods should be indirectly tested by any public interface...
With TDD, all of your code should be reachable from your public interface:
First you write the tests for your features.
Then you write the minimum amount of code for your tests to pass. This is the indication that your features are implemented.
If some code is not covered, this means that either this code is useless (remove it and run your tests again) or your tests are incomplete (some features have been implemented but not explicitely identified by a test).
You can test private with Reflection but it will be a pain later. I think you need to put your test in the same assembly (or package) and try to use Internal. This way you have some protection and you can test your stuff that you want to test.
If your private method is not indirectly tested by the public API test methods and it needs to be tested then I would delegate your main class to another secondary class.
public Stack {
public ... push(...) {...}
public ... pop(...) {...}
public ... isEmpty(...) {...}
// secondary class
private StackSupport stackSupport;
public StackSupport getStackSupport() {...}
public void setStackSupport(StackSupport stackSupport) {...}
}
public StackSupport {
public ...yourOldPrivateMethodToTest(...) {...}
}
Then your private method is a public method in another class. And you can test that public method in the another class tests. :-)
When coding using TDD, I create the public interface API for the object. That would mean in your example that my interface which the class implements would only have push(), pop() and isEmpty().
However testing these methods by calling them aren't unit tests in themselves (more on this at the end of this post), since they most likely test the co-operation of multiple inner methods which together produce the desired result and this is what your question is about: Should those methods be private?
My answer is no, use protected (or the equivalent of it in the language of your choice) for those instead of private which means that if your project and test POMs are structured similarly, the test suite class can see inside the actual class since they're virtually in the same folder. These can be considered unit tests: You're testing functional blocks of the class itself, not their co-operation.
As for testing the individual interface/API methods it's of course important to do that too and I'm not disputing that, those however fall somewhere between the hazy line of unit testing and acceptance testing.
In my opinion the most important thing to remember here is that unit tests tell you if a method misbehaves, acceptance tests tell if the co-operation of multiple methods'/classes' misbehave and integration testing tells if multiple systems' co-operation misbehaves.