Reputation: 179
I'm working on a Visual C++ project that has existed for 10+ years. We have just decided to start adding unit testing. Out group is debating two basic methodologies to allow for the unit tests to be written against a given class. Either we can derive a class and add what we need for unit testing in the derived class or we can make a base class and move what we need to only the base class, deriving our existing class from it.
Option 1:
class CExistingClass
class CDerivedClass : CExistingClass
Option 2:
class CBaseClass
class CExistingClass : CBaseClass
The advantage of option 1 is that it does not require any changes to the existing class - anything needed for unit testing is added on strictly for the unit class project and does not add anything to our existing library. The downside: It is a complete disaster when it comes time to try to link. To get it to work for one of our libraries, we had to add a separate post build step to perform a static link version of the library as well as add individual OBJ files to the Additional Dependencies.
The advantage of option 2 is that linking is not an issue - you pick up only the base class and test the items located within it. The downside is this means modifying existing code and generally lowers the readability of the software (which, after 10+ years was already too low to begin with). It also opens the door to multiple inheritance issues, which I would really like to avoid.
I haven't been able to find a discussion of anyone else going through this decision process and am interested to see what has been decided elsewhere and get any lessons learned, or better yet, and hear an option 3 we haven't considered.
Upvotes: 0
Views: 462
Reputation: 41747
I would suggest to split up your application into static libraries with clearly defined interfaces. Clear interface boundaries are the key here. You can link static libs directly into test DLLs. Consider having one test DLL per library.
You can link import libraries directly into test DLLs. That allows easy access to your functions for testing. For non-import libs, you could still go the GetProcAddress & LoadLibrary & FreeLibrary route to get the DLL exports called directly in your tests.
Or, if you have OBJ files from EXE building, add a post build action to assemble the OBJ files into a static lib, which you might then include in your testing project.
If things are cluttered: pull out the smallest piece of code that can be tested in isolation.
A must read: Working Effectively with Legacy Code, also by Michael Feathers, Prentice Hall, 2004.
Upvotes: 3
Reputation: 10211
Maybe I don't understand completely your question, would you test existing code or else refactor the existing code for test purpose?
Technically you don't have to change your code, but only test the public interface of your classes, if the problem is how better decouple for testing purpose, I think second choice is better, where the new base class will be abstract, but maybe I've missed the topic
Upvotes: 1