Recently, I have been working on a project that can be considered my first real test driven development experience. As the name implies, test driven development is an agile methodology that aims at producing code that has been fully tested. Another one of the most powerful advantages of test driven development is that if a developer modified the code, he can easily run the existing test suits and he would know if his modification broke any of the existing features in the code. Essentially, a developer starts thinking of the functionality that needs to be added to the existing code base. Then, before writing any code, he writes a test case (maybe a number of them) that will of course fail because the feature isn’t implemented yet. Then he would write the bare minimum code that would make the test cases pass. Then write more tests, then write more code to pass the tests …etc.
So, what’s the problem? Well, one of the main problems with Test Driven Development is testing private methods (assuming that you’re using an Object Oriented language). I googled the problem, and I found a number of solutions. Here is a list of the interesting ones along with the problems of each:
- Change the access modifier of the method to public/protected/internal/…etc., run your tests, then change it back to private
- Once you change the access modifiers back to private, your test cases won’t even compile.
- If I decided that a specific method needs to be private, why would I ever want to change it to public. It seems like a dirty walk around the problem and violation to the developer’s intended design.
- Philosophical solution: Test only public methods, which are assumed to call private ones.
- It is based on the unsolved debate of what unit testing really is.
- It sounds like “lets ignore the problem intentionally”
- If you’re using JUnit4, you can create your test cases in the same class you’re testing, which means you have access to its private methods.
- It results in a large sized release of your project. Because you have all test cases embedded in your code.
- What if your test case needs to test two private methods separated in two different classes?
- Use annotations/attributes/…etc.
- It isn’t a language independent solution
- Behind the scenes, these annotations change the accessibility of your methods. But again, this implementation is different in each language.
- I’d appreciate it if anyone shares any other solutions?
Luckily, I was able to find another solution that seems to satisfy my requirements. Although the solution is generic and language independent, I’ll explain it referring to Java. Before we go on, let me give you a quick introduction to the technologies that I used.
Aspect oriented programming is a technology intended to motivate separation of concerns. Usually developers refer to concerns as features that can be, but not necessarily, tied to the business logic. For example, logging, caching, exception handling, …etc. However, I think that it is safe to look at concerns as any feature that is required in your program. One of the most powerful tools that aspect oriented programming provides is called introduction. Basically, it means that you can introduce new fields, methods, or structure to your existing classes, which is the core tool behind my solution. [Have you guessed the solution yet?] Most language compilers have aspect oriented programming extensions. For example, AspectJ is one of the most common Java extensions that supports aspect oriented programming.
Alright here is how you can unit test private methods using aspect oriented programming:
- Create aspects that introduce public methods to the class under test
- In those public methods, you have access to all private methods and fields, call the private method and return the result.
- In your unit test, call the public method which is just a simple wrapper to the private method.
- Once your program is mature and ready to release, all you have to do is to build the source code without both of unit tests and AspectJ files.
Is it the best solution in the world? I don’t think so, and here is why:
- If I ever wanted to release my test cases as well as my source code, I have to ask other developers to install a new compiler, because the test cases won’t compile without applying (weaving) the aspects into the code base. In my case, the compiler is AspectJ.
- Developers in my team have to learn a new language constructs (aspects). However, I have to say that you can learn it in less than an hour. Probably, not master it ;).
Note: if you know of anyone that proposed this solution, please let me know so that I give him the credit for the idea. Also let me know if you’d like any sample source code to demonstrate the idea.
Please, share your thoughts!