Dear Testing Community, The Sogeti Testlab Hub Stuttgart wants to give you a short and practical guideline for the standard test levels used in agile SW-Projects. Diagram 1: The Test Pyramid – Unit testing should create a solid fundamental of the all over test coverage The hints and recommendations presented here are based on the experience of several testing workshops done with developers and test automation Experts in international projects with different Sogeti clients in the last year. As shown in the Test pyramid let’s start with the essential and basic test level, the unit test. This blog doesn’t regard the structural aspect but will discuss the methodological aspects of the functional unit test as listed in the test framework below (Diagram 4). Diagram 2: the 2 essential test types of unit testing As seen in the diagram above unit testing should comprise of a structural test executed for example by a structural code analyzer like SonarQube following the rules of the structural testing and functional testing using Frameworks out of the X-Unit framework catalogue. This blog talks about a methodological toolkit the developer should know and use in order to write trustworthy and purposeful test cases with his automation-framework. Definition of Unit Testing: Let’s follow Roy Osherove, 2015 who defines the unit test as follows: Diagram 3: The unit test in the context with the user’s view The unit test will prepare and control the GUI-based testing. This definition allows distinguishing the unit test level from the integration test level by indicating the fact that the unit tests build on a total data control organized by the developer and executed by the test framework. Each run of a test case has to produce the same result based on the same input test data. The exception will be discussed later. Diagram 4: Framework for the functional unit test Test Objects: What are now the basic test objects to be verified by unit testing? For the functional tests the following three test objects will be mainly addressed: Classes: Class calls (internal flow and dependencies) Methods: Member tests (generated data as return values) Objects: Object states (state-based testing) The classes will be tested concerning their call dependencies as it is designed in i.e. UML sequence diagrams. The methods will be tested for correctness and completeness of their target business data. The objects will be tested concerning their correct content and states and state transitions. A risk-based approach can be used by analyzing the test objects concerning their complexity and criticality. Sociable or solitaire Tests: Diagram 5: Martin Fowler According to Martin Fowler you may find two “schools” of unit testers in the programming community. The classical school: The “classicists” accept the dependencies of the tested classes to other classes and open the data interfaces. So they don’t use test doubles and are working with the test data provided by the neighbor-classes. They are doing sociable tests. (i.e.: price method invokes functions from the product and customer class). Prerequisite: The data resource must be stable in order not to violate the definition given by Roy Osherove. The “mockist” school: Following strictly the definition of the unit test and using stubs and mocks to isolate the class tests and keeping a total control of the test data. Risk based Unit Analyses: A risk-based approach can be used in order to analyze, evaluate, control and manage the test objects. Two characteristics of the test objects have to be understood: Complexity and Criticality. Complexity: According to Robert Binder, 2000, the complexity of a class consists of the Runtime execution dependencies between methods and between methods and objects in a class. As we can see in diagram 5 four types of complexity will be differentiated:
- non modal: Methods can be executed randomly i.e. Date time
- uni-modal: Methods can only be executed in a certain order i.e. TrafficLight
- Quasi modal: Methods can be executed in dependency of the Object state i.e. Stack operations (First in, Last out)
- Modal: Methods can only be executed in a certain order and in dependency with the object state i.e. banking account