Certain semantic conventions used in Qt-based applications dictate specific ways in which unit tests should and should not be constructed. In particular:
- Many Qt classes take the Parent pointer as a constructor parameter. Not all subclasses of the base type specified for that parameter are semantically valid for any given Qt class.
- Qt Parent objects take ownership of their children, including memory management. This implies that Parents delete children when they are deleted themselves.
Implications for automatically-generated test cases are as follows:
- Automatically-generated tests create primary and secondary test objects on the stack. In most cases, this will conflict with convention #2 above, resulting in memory errors during test case execution, with stack traces most likely pointing to the closing brace of a destructor.
- In automatically-generated tests, C++test will attempt to use any available subclass type for an argument of a base type. In many cases, this will conflict with issue #1 above.
- If tests require definition of the QApplication variable, the macro definition
- DCPPTEST_INIT_QT=1
should be added to the compiler options. To use the Qt console application,also add the macro-DCPPTEST_INIT_QT_CONSOLE=1
.
We recommend the following procedure for unit testing Qt-based classes:
- Automatically generate unit tests; this will give you a template.
- Keep one of the generated tests as a template, preferably one that passes (does not throw an exception) when run.
- Using the one test as a template, replace test object allocations by declaration with those on the heap (using new).
- At the end of the test, if a parent object is used, delete only that—whether it is the primary test object or a secondary test object.
- Validate the one test by using a debugger to observe the final test object states and inserting appropriate assertion macros.
- Add more test cases (using the GUI dialog option, and using the first validated test case as the template).