Reputation: 241
In C++ how would one test a class constructor? For example:
Class myClass{
int a;
public:
myClass(); //Constructor
void reset(); //resets a to 0;
};
//Constructor defined to initialize a to 0
myClass::myClass(){
reset();
}
//reset sets a to 0
void myClass::reset(){
a = 0;
}
How would I test the myClass() constructor? I can't access the private data member, so would it be valid to say if reset works then the constructor works?
Upvotes: 4
Views: 9683
Reputation: 3727
I am going to rephrase your question to: how do I test properties of my class that are not directly observable from my tests because they are protected or private? Here are several possibilities in the order that I usually think about them:
Move the checking part of the test into the class by using an assert(). If what you want to test is that your constructor has successfully established some complex invariant, then you can put an assert() at the end of the constructor that verifies that invariant. Then all your test has to do is to call the constructor - the assert inside the constructor does the actual checking that the test would otherwise have done. If you habitually add asserts as you write the code then that assert will already be there (if asserts make your debug build too slow, use a profiler to pinpoint those asserts that are actually a problem).
Extract the complex piece of code that you want to test into a second class. You can then test the second class through its public interface. This option is attractive when extracting the second class improves the code even when not considering testability.
Change the design of your code to something more testable in some other way. Again, this is attractive when the change is an improvement even when not considering testability.
Strategic retreat. Testing code in isolation is good all other things being equal, but there is no law saying that all code must be tested in isolation. Sometimes the right answer is to just let that code be tested as a side-effect of testing something else. All your other tests for that class will call the constructor, after all, so if something is wrong with the constructor it will probably cause one of those other tests to fail. It may be harder to cover all paths this way and at the time that you get that failure it will be more trouble to track down the cause of the failure because now you do not know if the problem is the constructor or the other thing being tested. That may or may not be a big deal. Is it truly worth the trouble to test this code in isolation, taking into consideration what else you could be using that time on and the probability that this test will ever actually find a bug? Would a code review be a more useful way to spend that time? Is there something else that it would be more useful to do?
If you truly must test something that cannot be tested with assert() and where there is no acceptable refactoring to improve testability, then there are still some options. I've never had to use these for testing, but here they are:
Use a friend declaration to give your tests access to private fields on your class. Each class now needs to maintain a list of friend declarations for tests that need access. This can be a chore to maintain.
Maintain a separate interface for use by tests. Have a set of methods that give the access that you need and whose name has a prefix like "testOnly". So in your case it would be testOnlyGetA(). You will have to be disciplined in only calling these methods from tests and you now need to maintain a larger interface than before.
Hold your nose and do #define private public
in your test file before including the header that you want to test.
Upvotes: 10
Reputation: 54
You can declare a test class with the same memory layout of your original class, but all members being public.
void testMyClassConstructor()
{
class myClassPublic
{
public:
int a;
myClassPublic();
void reset();
};
typedef union
{
myClass* original;
myClassPublic* testView;
} u_myClass;
myClass testInstance;
u_myClass testUnion;
testUnion.original = &testInstance;
assert(testUnion.testView->a == 0);
}
This is fine in a white box test case, if you can't change the tested class' interface. However, remember that any changes to the memory layout of the original class will break the unit test aswell.
Upvotes: -1
Reputation: 33904
You could add a boost test case to the class:
Class myClass{
private:
int a;
public:
myClass(); //Constructor
void reset(); //resets a to 0;
void test_a_reset() {
BOOST_CHECK_EQUAL(a, 0);
}
};
Im not sure about how you are doing the testing though. This may not be what you want.
Upvotes: 0
Reputation: 1830
Upd. Sorry, misunderstood.
You may add a friend testing function to a class or a class-member testing function (which is better to test implementation details, but sometimes is impossible due to testing framework restrictions)
Upvotes: 0