A tenant of OOP]. In Inheritance, a new class inherits properties and behaviours from an existing class.
Testing
People thought that inheritance would reduce the need for testing:
- If we have a well-tested superclass, we can reuse its code (in subclasses, through inheritance) with confidence and without retesting inherited code
- A good test suite used for a superclass will also be acceptable for a subclass Both claims are wrong.
Why Retest?
- When we modify a superclass, we need to retest the subclasses. Additionally, we need to retest the methods for subclasses that were inherited from superclasses since these methods execute in a new context. This is because things in the subclass could break an invariant established in the superclass.
- OOP also allows us to completely override a superclass method
- Ex. if m calls m2 in A but m2 is overridden in A2, we need to retest m
- To get full coverage, we need to test all method interactions
Testing Abstract Classes
We obviously can’t instantiate an abstract or virtual class but they define an interface that implementing classes need to adhere to. We need to test these classes for functional compliance.
Functional Compliance
This is a module’s compliance with some documented or published functional specification.
Liskov Substitution Principle
Objects of subtypes should behave like those of super types if used via super type methods.
- The invariants of the super type must not be violated or broken by the sub type
- The pre conditions on an overridden method for the sub type must be a subset of the preconditions on the same method for the super type
- The post conditions on an overridden method for the sub type must be a super set of the post conditions on the same method for the super type
Abstract test pattern rules:
- Write an abstract test class for every interface and abstract class
- An abstract test should have test cases that cannot be overridden
- It should also have an abstract factory method for creating instances of the class to be tested
- Write a concrete test class for every implementation of the interface or abstract class
- The test class should extend the abstract test class and implement the factory method
- Tests that define the functionality of the interface belong in the abstract test class
- Tests specific to an implementation belong in a concrete test class