Introducing C++ into an embedded project is a major challenge for most teams. Underestimating the effort involved can potentially delay the entire development process. And now, the C++ software is supposed to undergo additional complex security testing?
Is it even possible to test quality into C++ software?
Object-oriented programming, while offering attractive features, also introduces new sources of error into the project. These include complex properties such as data encapsulation, inheritance, association, aggregation, composition, polymorphism, and dynamic binding.
Objects and instances of classes are used in different contexts or can be in different states that affect their behavior (different constructors), and they have relationships that need to be tested. With dynamic binding (polymorphism), every possible binding, as well as the shift of control flow from procedures to messages between classes, should be carefully tested.
What additional tests are required for C++ software?
At the top of the list of elements to be tested are the classes. We will examine them more closely from several perspectives. Testing class hierarchies This occurs vertically along the inheritance hierarchy and horizontally along the relationships to other classes.

Image 1: Class hierarchy
The Class architectures Testing is performed based on the class diagrams, proceeding along the class hierarchy from the base class to the derived class. The base class is tested first. The third step involves testing the... Class integration testt through. Based on sequence diagrams along the associations, the interaction of the individual objects and the correct calling of functions are particularly important.

Image 2: Class structure, class hierarchy without inheritance
Both Class and integration tests The most important thing is that all methods are executed and all parameters and return values are used correctly (equivalence class and boundary value tests). Does the system handle valid and invalid parameters correctly (positive and negative tests)? Is an outgoing exception thrown and an incoming exception treated as "xx becomes xx"? For classes with stateful behavior, it should be tested whether every state is reached and every method is executed in every state of the object, as well as all state transitions. This includes testing all relationships for incorrect or missing connections and incorrect multiplicities.

Figure 3: Class with state behavior
At the Testing for heredity First, we examine the methods and attributes in the base class. Since these methods and attributes can be inherited, we must also re-examine inherited methods and attributes from tested base classes in the context of the derived class. Methods of a derived class can be overridden.
Testing polymorphic structures: If multiple methods with the same signature appear at different hierarchy levels within an inheritance branch of a class hierarchy, we determine at runtime which method from which inheritance path is used for a given object. With deep class hierarchies, it can be difficult to trace which method is called. Ensure that the classes involved are instantiated. Every possible binding should also be tested.

Figure 4: Polymorphism, abstract classes and interfaces
Software that is easy to test leads to new software design requirements.
Security is also a matter of well-written code. Just as in embedded systems, a well-thought-out software architecture is essential from the outset for C++ software to achieve a reliable quality standard. In terms of easily testable software, this can also lead to new software design requirements within the framework of object-oriented programming.
Multiple and repeated inheritances lead to greater difficulty in understanding inheritance patterns and thus increase the likelihood of errors. The best way to counteract this is to avoid deep inheritance hierarchies. The same applies to polymorphism and dynamic binding.
Sources of error
There are numerous potential sources of error when programming parallel processes in object-oriented systems. The following is an overview of the most important tests for avoiding such errors:
- Sources of error to be tested when waiting for synchronization events:
- Unnecessary waitingComputing power is lost – operation sequences cannot be executed, even though they should be executable.
- Waiting too long: Timeout is not detected – the process „starves“ (starvation/deadlock).
- Lack of waiting: unauthorized process overlap/overlap
- Shared VariablesVariables are used by different, concurrent processes.
- Race ConditionsTime-critical processes can produce different results even with the same input values.
- News conflictsThese can occur during communication and synchronization, e.g., an incorrect order of messages due to different external influences.

Figure 5: Multitasking, parallel software processing
Conclusion
Proper testing of object-oriented systems should be included in the project budget from the outset. If this is neglected in favor of faster or cheaper project completion, the damage is incalculable. The quality of your software depends on both choosing the right software architecture and having a thorough understanding of the programming language. In-depth testing expertise will enable you to achieve a high level of quality for your software and gain a significant competitive advantage.
Further information
Training: Embedded Software Testing – Best Practices for Unit/Module/Component Testing
MicroConsult Training & Coaching on the topic of Testing and Debugging
MicroConsult Training & Coaching on the topic of software development

