C++ Unit Testing – What is the Correct Approach to Test Classes with Inheritance?

ctestingunit testing

Assuming I have the following (over-simplified) class structure:

class Base
{
  public:
    Base(int valueForFoo) : foo(valueForFoo) { };
    virtual ~Base() = 0;
    int doThings() { return foo; };
    int doOtherThings() { return 42; };

  protected:
    int foo;
}

class BarDerived : public Base
{
  public:
    BarDerived() : Base(12) { };
    ~BarDerived() { };
    int doBarThings() { return foo + 1; };
}

class BazDerived : public Base
{
  public:
    BazDerived() : Base(25) { };
    ~BazDerived() { };
    int doBazThings() { return 2 * foo; };
}

As you can see, the doThings function in the Base class returns different results in each Derived class due to the different values of foo, while the doOtherThings function behaves identically across all classes.

When I wish to implement unit tests for these classes, the handling of doThings, doBarThings / doBazThings is clear to me – they need to be covered for each derived class. But how should doOtherThings be handled? Is it good practice to essentially duplicate the test case in both derived classes? The issue becomes worse if there are half a dozen functions like doOtherThings, and more Derived classes.

Best Answer

In your tests for BarDerived you want to prove that all (public) methods of BarDerived work correctly (for the situations you have tested). Similarly for BazDerived.

The fact that some of the methods are implemented in a base class does not change this testing goal for BarDerived and BazDerived. That leads to the conclusion that Base::doOtherThings should be tested both in the context of BarDerived and BazDerived and that you get very similar tests for that function.

The advantage of testing doOtherThings for each derived class is that if the requirements for BarDerived change such that BarDerived::doOtherThings must return 24, then the test failure in the BazDerived testcase tells you that you might be breaking the requirements of another class.