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.