Testing Object-Oriented Systems: Models, Patterns, and Tools
Robert V. Binder
Contents
Preface
Acknowledgements
Part I: Preliminaries
1 A Small Challenge
2 How to Use This Book
2.1 Reader Guidance
2.2 Conventions
2.2.1 Chapter Elements
2.2.2 Degree of Difficulty
2.2.3 Standards
2.2.4 Object-oriented Terminology
2.2.5 Programming Languages and Code Examples
2.2.6 Testing Tools
2.2.7 Humility Department, or Bug Reports Cheerfully Accepted
2.3 A FAQ for Object-Oriented Testing
2.3.1 Why Test Objects?
2.3.2 Test Design
2.3.2.1 General Testing Issues
2.3.2.2 Test Design for Methods and Classes
2.3.2.3 Testing for Reuse
2.3.2.4 Subsystems and Application Systems
2.3.2.5 Integration Testing and Order of Development
2.3.2.6 Regression Testing and Iterative, Incremental Development
2.3.2.7 Testing with UML Models
2.3.3 Test Automation
2.3.4 Test Process
3 Testing: a Brief Introduction
3.1 What is Software Testing?
3.2 Definitions
3.3 The Limits of Testing
3.3.1 The Input/State Space
3.3.2 Execution Sequences
3.3.3 Fault Sensitivity and Coincidental Correctness
3.3.4 Absolute Limitations
3.4 What Can Testing Accomplish?
3.5 Bibliographic Notes
4 With the Necessary Changes: Testing and Object-Oriented Software
4.1 The Dismal Science of Software Testing
4.1.1 I'm Okay, You're Okay, Objects are Ok
4.1.2 The Role of a Fault Model
4.1.3 Fault Models for Object-Oriented Programming
4.2 Side Effects of the Paradigm
4.2.1 What Goes Wrong?
4.2.2 Encapsulation
4.2.3 Inheritance
4.2.3.1 Incorrect Initialization and Forgotten Methods
4.2.3.2 Testing Axioms
4.2.3.3 Inheritance Structure
4.2.3.4 Multiple Inheritance
4.2.3.5 Abstract and Generic Classes
4.2.4 Polymorphism
4.2.4.1 Dynamic Binding
4.2.4.2 The Yo-Yo Problem
4.2.5 Message Sequence and State related Bugs
4.2.5.1 Message Sequence Model
4.2.5.2 Equivalent Sequences
4.2.5.3 Implications of Cooperative Design
4.2.5.4 Observability of State Faults
4.2.5.5 Non-specific State Faults
4.2.6 Built-in Low Level Services
4.2.7 Bug Lists
4.3 Language Specific Hazards
4.3.1 C++
4.3.2 Java
4.3.3 Smalltalk
4.4 Coverage Models For Object-Oriented Testing
4.4.1 Code Coverage and Fault Models
4.4.2 Optimistic Scope
4.4.3 Method Scope Branch Coverage
4.4.4 Coverage for a Classless Language
4.4.5 ICpak Test Suite
4.4.6 Coverage Checklist
4.4.7 Incremental Class Testing
4.4.8 Class Interface Dataflow Coverage
4.4.9 Polymorphic Bindings
4.5 An OO Testing Manifesto
4.6 Bibliographic Notes
Part II: Models
Introduction to Part II
5 Test Models
5.1 Test Design and Test Models
5.1.1 Why Testing Must be Model-based
5.1.2 What is a Model?
5.1.3 The Role of Models in Testing
5.1.4 Cartoons or Test-Ready Models?
5.1.5 Consequences
5.2 Bibliographic Notes
6 Combinational Logic
6.1 How Combinational Models Support Testing
6.2 How to Develop A Decision Table
6.2.1 Basic Approach
6.2.2 Components and Structure
6.2.3 The Auto Insurance Renewal Model
6.2.4 Don't Care, Don't Know, Can't Happen
6.2.5 Decision Tables in OO Development
6.3 Deriving the Logic Function
6.3.1 Boolean Expressions
6.3.2 TruthTables versus Decision Tables
6.3.3 Elements of Boolean Expressions
6.3.4 Karnaugh-Veitch Matrix
6.3.5 Cause-Effect Graphs
6.4 Decision Table Validation
6.5 Test Generation
6.5.1 Fault Model
6.5.2 All Explicit Variants
6.5.3 All-Variants, All-True, All-False, All-Primes
6.5.4 Each-Condition/All-Conditions
6.5.5 Binary Decision Diagram Determinants
6.5.6 Variable Negation
6.5.7 Nonbinary Variable Domain Analysis
6.5.8 Additional Heuristics
6.6 Choosing a Combinational Test Strategy
6.7 Bibliographic Notes
7 State Machines
7.1 Motivation
7.2 The Basic Model
7.2.1 What is a State Machine?
7.2.2 State Transition Diagrams
7.2.3 Some Properties of Finite State Automata
7.2.4 Guarded Transitions
7.2.5 Mealy and Moore
7.2.6 State Transition Tables
7.2.7 Limitations of the Basic Model
7.2.8 Statecharts
7.2.9 State Machines and Object-Oriented Development
7.3 The FREE State Model
7.3.1 Limitations of OOA/D Behavior Models
7.3.2 States
7.3.2.1 A State is a Value Set
7.3.2.2 State Invariants
7.3.2.3 Scope and Granularity
7.3.2.4 No Hybrids Allowed
7.3.3 Transitions
7.3.4 Alpha and Omega States
7.3.5 Inheritance and Class Flattening
7.3.5.1 Flattening the Class Hierarchy
7.3.5.2 Expanding the Statechart
7.3.6 Unspecified Event/State Pairs
7.3.6.1 The Response Matrix
7.3.6.2 Designing Responses to Illegal Events
7.4 State-based Test Design
7.4.1 How State Machines Fail
7.4.1.1 Control Faults
7.4.1.2 Incorrect Composite Behavior
7.4.2 Developing a Testable Model
7.4.2.1 When and How
7.4.2.2 State Model Validation
7.4.3 The N+ Test Strategy
7.4.3.1 The ThreePlayerGame Example
7.4.3.2 Generate the Round-trip Path Tree
7.4.3.3 Sneak Paths: Illegal Transitions and Evading the Guard
7.4.3.4 Event Path Sensitization
7.4.3.5 Built-in Test Support
7.4.4 Relative Power and Limitations
7.4.5 Choosing a State-based Test Strategy
7.5 Bibliographic Notes
8 A Tester's Guide to the UML
8.1 Introduction
8.1.1 The UML as a Test Model
8.1.2 Relational Testing Strategy
8.2 General Purpose Elements
8.2.1 Organization and Annotation
8.2.2 Object Constraint Language
8.3 Use Case Diagram
8.3.1 Notation and Semantics
8.3.2 Generic Test Model
8.3.3 Testability Extensions
8.3.3.1 Operational Variables
8.3.3.2 The Operational Relation
8.4 Class Diagrams
8.4.1 Notation and Semantics
8.4.1.1 Association
8.4.1.2 Aggregation
8.4.1.3 Generalization
8.4.2 Generic Test Model
8.5 Sequence Diagram
8.5.1 Notation and Semantics
8.5.2 Generic Test Requirements
8.5.3 Testability Extensions
8.6 Activity Diagram
8.6.1 Notation and Semantics
8.6.2 Generic Test Model
8.7 Statechart Diagram
8.8 Collaboration Diagram
8.8.1 Notation and Semantics
8.8.2 Generic Test Model
8.8.3 Testability Extensions
8.9 Component Diagram
8.9.1 Notation and Semantics
8.9.2 Generic Test Model
8.10 Deployment Diagram
8.10.1 Notation and Semantics
8.10.2 Generic Test Model
8.11 Graphs, Relations, and Testing
8.12 Bibliographic Notes
Part III: Patterns
Introduction to Part III
9 Results-Oriented Test Strategy
9.1 Results-Oriented Testing
9.1.1 The Role of Responsibility-Based Test Design
9.1.1.1 Class Responsibilities
9.1.1.2 Why Test from Responsibility Models?
9.1.2 The Role of Implementation-based Test Design
9.1.3 Integration in Object-oriented Development
9.1.4 Harnessing Responsibility and Implementation
9.2 Test Design Patterns
9.2.1 What is a Pattern?
9.2.2 Patterns and Testing
9.2.3 Test Design Pattern Template
9.2.4 Test Patterns in this Book
9.2.5 Using Test Design Patterns
9.3 Documenting Test Cases, Suites, and Plans
9.3.1 IEEE 829 Documentation
9.3.2 Traceability
9.4 Bibliographic Notes
10 Classes
10.1 Class Test and Integration
10.1.1 What is Class Scope Testing?
10.1.2 Why Test at Class Scope?
10.1.3 Who and When
10.1.4 A Case Study: MPR Teltech
10.2 Preliminaries
10.2.1 Class Scope Integration
10.2.1.1 Small Pop
10.2.1.2 Alpha-Omega Cycle
10.2.2 Implementation-Based Test Models
10.2.2.1 The Role of Code Coverage
10.2.2.2 A Code Coverage FAQ
10.2.2.3 Method Scope Code Coverage Models
10.2.2.4 The Class-Flow Graph: a Class-scope Coverage Model
10.2.2.5 Once More With Feeling: The Dark Side of Code Coverage
10.2.3 Path Sensitization
10.2.4 Domain Testing Models
10.2.4.1 Domain Analysis
10.2.4.2 On, Off, In, and Out
10.2.4.3 Boundary Conditions with Two or More Variables
10.2.4.4 Modeling the Domain of Objects
10.2.4.5 The One by One Selection Criteria
10.2.4.6 The Domain Test Matrix
10.3 Method Scope Test Design Patterns
10.3.1 Considerations
10.3.1.1 Functional Cohesion
10.3.1.2 Method Scope Integration
10.3.1.3 The Patterns
10.3.2 Category-Partition
10.3.3 Combinational Function Test
10.3.4 Recursive Function Test
10.3.5 Polymorphic Message Test
10.4 Class Scope Test Design Patterns
10.4.1 Considerations
10.4.1.1 Class Modalities
10.4.1.2 The Patterns
10.4.2 Invariant Boundaries
10.4.3 Non-modal Class Test
10.4.4 Quasi-Modal Class Test
10.4.5 Modal Class Test
10.5 Flattened Class Scope Test Design Patterns
10.5.1 Considerations
10.5.1.1 The Trouble with Superclasses
10.5.1.2 Test Strategy for Flattened Classes
10.5.1.3 The Patterns
10.5.2 Polymorphic Server Test
10.5.3 Modal Hierarchy Test
10.6 Bibliographic Notes
11 Reusable Components
11.1 Testing and Reuse
11.1.1 Reuse Mechanisms
11.1.2 The Role of Testing in Reuse
11.1.3 Reusing Test Suites
11.2 Test Design Patterns
11.2.1 Abstract Class Test
11.2.2 Generic Class Test
11.2.3 New Framework Test
11.2.4 Popular Framework Test
11.3 Bibliographic Notes
12 Subsystems
12.1 Subsystems
12.1.1 What is a Subsystem?
12.1.2 Why Test at Subsystem Scope?
12.2 Subsystem Test Design Patterns
12.2.1 Class Association Test
12.2.2 Round-trip Scenario Test
12.2.3 Controlled Exception Test
12.2.4 Mode Machine Test
12.3 Bibliographic Notes
13 Integration
13.1 Integration in Object-Oriented Development
13.1.1 Definitions
13.1.2 Integration Testing Is Essential
13.1.3 Dependency Analysis
13.1.4 Integration Faults
13.2 Integration Patterns
13.2.1 Scope Specific Considerations
13.2.1.1 Classes
13.2.1.2 Clusters
13.2.1.3 Subsystem/System Scope
13.2.2 Big Bang Integration Test
13.2.3 Bottom Up Integration Test
13.2.4 Top Down Integration Test
13.2.5 Collaboration Integration Test
13.2.6 Backbone Integration Test
13.2.7 Layer Integration Test
13.2.8 Client/Server Integration Test
13.2.9 Distributed Services Integration Test
13.2.10 High Frequency Integration
13.3 Bibliographic Notes
14 Application Systems
14.1 Testing Application Systems
14.1.1 A Cautionary Tale
14.1.2 Testing Object-Oriented Application Systems
14.1.3 Application System Test Strategy
14.2 Test Design Patterns
14.2.1 Extended Use Case Test
14.2.2 Covered in CRUD
14.2.3 Allocate Tests by Profile
14.3 Implementation-Specific Capabilities
14.3.1 Configuration and Compatibility
14.3.2 Performance
14.3.3 Integrity and Fault Tolerance
14.3.3.1 Concurrency Testing
14.3.3.2 Stress Testing
14.3.3.3 Restart/Recovery Testing
14.3.4 Human-Computer Interaction
14.4 Post-Development Testing
14.5 Note on Testing Performance Objectives
14.6 Bibliographic Notes
15 Regression Testing
15.1 Preliminaries
15.1.1 What and Why
15.1.2 When and How
15.1.3 Regression Faults
15.1.4 Test Automation
15.1.5 Test Suite Maintenance
15.1.6 Considerations for Reducing a Test Suite
15.1.6.1 Safe Reduction
15.1.6.2 Unsafe Reduction
15.2 Test Patterns
15.2.1 Retest All
15.2.2 Retest Risky Use Cases
15.2.3 Retest By Profile
15.2.4 Retest Changed Code
15.2.5 Retest Within Firewall
15.3 Bibliographic Notes
Part IV: Tools
Introduction to Part IV
16 Test Automation
16.1 The Test Automation Imperative
16.1.1 Why Testing Must be Automated
16.1.2 Limitations and Caveats
17 Assertions
17.1 Introduction
17.1.1 What are Assertions?
17.1.2 Why Use Assertions?
17.1.3 Who Uses Assertions?
17.1.3.1 A Million Lines of Built-in Test: OS/400
17.2 Implementation-based Assertions
17.2.1 Assumption Checkers
17.2.2 Dark Alleys, Lurking Faults, and Sniffers
17.3 Responsibility-based Assertions
17.3.1 Overview
17.3.2 Responsibilities, Contracts, and Subtypes
17.3.2.1 The Contract Metaphor
17.3.2.2 Assertions and the UML
17.3.2.3 Assertion Strength and Weakness
17.3.3 Method Scope
17.3.3.1 Preconditions
17.3.3.2 Loops
17.3.3.3 Postconditions
17.3.4 Class Scope
17.3.5 Sequential Constraints
17.3.5.1 State Invariant
17.3.5.2 Accepting and Resulting Conditions
17.3.5.3 Run-Time Sequence Checking
17.3.6 Super/Subclass Scope
17.3.6.1 Subcontracts and Type Substitution
17.3.6.2 Buggy Inheritance
17.3.7 Client/Server Scope
17.3.7.1 Public and Private Contracts
17.3.7.2 Defensive Contracts?
17.3.7.3 Exceptions
17.4 Implementation
17.4.1 A Programmer's Assertion FAQ
17.4.2 Assertion Actions
17.4.3 Non-executable Assertions
17.4.4 Ada 95
17.4.4.1 Assert Pragma
17.4.4.2 Inline Assertion Procedure
17.4.5 C++
17.4.5.1 assert.h Macro
17.4.5.2 Assert Template
17.4.5.3 The Coherence Idiom
17.4.5.4 Exceptions
17.4.5.5 Tips and Tricks
17.4.6 Eiffel
17.4.7 Java
17.4.7.1 Basic Checking Capabilities
17.4.7.2 Final Static/Short Circuit Idiom
17.4.8 Objective-C
17.4.8.1 OpenStep Foundation Kit Assertion Macros
17.4.9 Smalltalk
17.4.9.1 Context Assertion Method
17.4.9.2 Design-by-contract Extensions
17.4.10 The Percolation Pattern
17.5 Deployment
17.5.1 Verification of Built-in Test
17.5.2 Using Assertions to Design Tests
17.5.2.1 Unarticulated Contracts
17.5.2.2 Practical Considerations
17.5.2.3 Test Suite Reduction
17.5.3 Pre-release Considerations
17.5.4 Post-release Considerations
17.6 Limitations and Caveats
17.7 Some Assertion Tools
17.8 Bibliographic Notes
18 Oracles
18.1 Introduction
18.2 Oracle Patterns
18.2.1 Introduction
18.2.1.1 Design Considerations
18.2.1.2 Choosing an Approach
18.2.1.3 Pattern Summary
18.2.2 Judging
18.2.3 Pre-specification Oracles
18.2.3.1 Solved Example Oracle
18.2.3.2 Simulation Oracle
18.2.3.3 Approximation Oracle
18.2.3.4 Parametric Oracle
18.2.4 Gold Standard Oracles
18.2.4.1 Trusted System Oracle
18.2.4.2 Parallel Test Oracle
18.2.4.3 RegressionTest Oracle
18.2.4.4 Voting Oracle
18.2.5 Organic Oracles
18.2.5.1 Smoke Test
18.2.5.2 Built-in Test Oracle
18.2.3.3 Reversing Oracle
18.2.3.4 Built-in Check Oracle
18.2.5.5 Executable Specification Oracle
18.2.5.6 Generated Implementation Oracle
18.2.5.7 Different But Equivalent Oracle
18.3 Comparators
18.3.1 Introduction
18.3.2 Determining Object Equality
18.3.3 Deep and Shallow Equality
18.3.4 Abstract Content versus Concrete Content
18.3.5 Aliases
18.3.6 Collections
18.3.7 Type/Subtype Equality
18.3.8 Partial Equality Methods
18.4 Bibliographic Notes
19 Test Harness Design
19.1 How to Develop a Test Harness
19.1.1 Requirements
19.1.2 Architecture
19.2 Test Case Patterns
19.2.1 Considerations
19.2.2 Test Case/Test Suite Method
19.2.3 Test Case/Test Suite Class
19.2.4 Catch All Exceptions
19.3 Test Control Patterns
19.3.1 Considerations
19.3.2 Server Stub
19.3.3 Server Proxy
19.4 Driver Patterns
19.4.1 Considerations
19.4.1.1 Design Goals
19.4.1.2 Inheriting Test Suites
19.4.1.3 Controllability, Observability, and Reuse
19.4.1.4 Driver Design Patterns
19.4.2 TestDriver Superclass
19.4.3 Percolate the Object Under Test
19.4.4 Symmetric Driver
19.4.5 Subclass Driver
19.4.6 Private Access Driver
19.4.7 Test Control Interface
19.4.8 Drone
19.4.9 Built-in Test Driver
19.5 Test Execution Patterns
19.5.1 Command Line Test Bundle
19.5.2 Incremental Testing Framework
19.5.3 Fresh Objects
19.6 A Test Implementation Syntax
19.7 Bibliographic Notes
Appendix: BigFoot's Tootsie -- a Case Study
20.1 Requirements
20.2 OOA/D for Capability-driven Testing
20.3 Implementation
20.3.1 Test Control Strategy
20.3.2 Some Test Automation Scenarios.
Glossary
Index
Copyright (C) 2000, Robert V. Binder, all rights reserved.