Search code examples
c++unit-testingcopy-constructorassignment-operator

Unit testing copy constructr and assignment operator


I am writing unit tests for a few classes (C++), and came across an issue attempting to write a unit test for the copy constructor and assignment operator. A basic thing that could be wrong with either is that a programmer adds a member to the class and then forgets to update the c'ctor and/or operator=.

I could of course write a unit test along the lines of:

class MyClass()
{
public:

    int a, b;
    non_trivial_copyable nasty;

    MyClass& operator=(const MyClass& _r)
    {
        if(this == &r)
          return *this;
        a = _r.a;
        b = _r.b;
        nasty = acquire_non_trivial_copyable();
    }
};


TEST(My_Class_copy_op)
{
  MyClass m1;
  m1.a = m1.b = 2;

  MyClass m2 = m1;
  VERIFY(m2.a == 2);
  VERIFY(m2.b == 2);
}

Very well. now the programmer adds a member c, but doesn't update the operator and test case.

class MyClass()
{
public:
    float c;
// ...
}

The test case will still merrily succeed, even though the operator is now broken.

Now, we could do the following:

TEST(My_Class_copy_op)
{
// Aha! Fails when programmer forgets to update test case to include checking c
   static_assert(sizeof(MyClass) == 8);
// Meh, also fails on an architecture where the size of MyClass happens to be != 8

   // ...
}

I could not find any good information on how to solve this, but sure someone must have ran into this before!? Is is so obvious that I'm missing it completely!?


Solution

  • Explicitly testing a copy constructor is fine, but it's probably beating around the bush. More often that not, the copy constructor itself is a detail you don't need to explicitly test. What you probably want to do instead is to write a suite of tests that do work on your copied object and make sure that the work comes up with the correct results. Like this:

    MyClass a;
    // Now initialize a with stuff it needs to do its job
    
    // Copy a into b
    MyClass b = a;
    
    // Make b do its job and make sure it succeeds
    VERIFY(b.DoWork());