You are previewing Developer Testing: Building Quality into Software.
O'Reilly logo
Developer Testing: Building Quality into Software

Book Description

How do successful agile teams deliver bug-free, maintainable software—iteration after iteration? The answer is: By seamlessly combining development and testing. On such teams, the developers write testable code that enables them to verify it using various types of automated tests. This approach keeps regressions at bay and prevents “testing crunches”—which otherwise may occur near the end of an iteration—from ever happening. Writing testable code, however, is often difficult, because it requires knowledge and skills that cut across multiple disciplines.

In Developer Testing, leading test expert and mentor Alexander Tarlinder presents concise, focused guidance for making new and legacy code far more testable. Tarlinder helps you answer questions like: When have I tested this enough? How many tests do I need to write? What should my tests verify? You’ll learn how to design for testability and utilize techniques like refactoring, dependency breaking, unit testing, data-driven testing, and test-driven development to achieve the highest possible confidence in your software. Through practical examples in Java, C#, Groovy, and Ruby, you’ll discover what works—and what doesn’t.

You can quickly begin using Tarlinder’s technology-agnostic insights with most languages and toolsets while not getting buried in specialist details. The author helps you adapt your current programming style for testability, make a testing mindset “second nature,” improve your code, and enrich your day-to-day experience as a software professional. With this guide, you will

  • Understand the discipline and vocabulary of testing from the developer’s standpoint

  • Base developer tests on well-established testing techniques and best practices

  • Recognize code constructs that impact testability

  • Effectively name, organize, and execute unit tests

  • Master the essentials of classic and “mockist-style” TDD

  • Leverage test doubles with or without mocking frameworks

  • Capture the benefits of programming by contract, even without runtime support for contracts

  • Take control of dependencies between classes, components, layers, and tiers

  • Handle combinatorial explosions of test cases, or scenarios requiring many similar tests

  • Manage code duplication when it can’t be eliminated

  • Actively maintain and improve your test suites

  • Perform more advanced tests at the integration, system, and end-to-end levels

  • Develop an understanding for how the organizational context influences quality assurance

  • Establish well-balanced and effective testing strategies suitable for agile teams

  • Table of Contents

    1. About This E-Book
    2. Title Page
    3. Copyright Page
    4. Dedication Page
    5. Contents
    6. Foreword by Jeff Langr
    7. Foreword by Lisa Crispin
    8. Preface
      1. Why I Wrote This Book
      2. Target Audience
      3. About the Examples
      4. How to Read This Book
    9. Acknowledgments
    10. About the Author
    11. Chapter 1. Developer Testing
      1. Developers Test
      2. Developer Testing Activities
        1. Unit Testing
        2. Integration Testing
        3. Maintenance
        4. Continuous Integration
        5. Test Automation
      3. What Developers Usually Don’t Do
      4. Defining Developer Testing
      5. Developer Testing and the Development Process
      6. Summary
    12. Chapter 2. Testing Objectives, Styles, and Roles
      1. Testing and Checking
      2. Testing Objectives
        1. Testing to Critique
        2. Testing to Support
      3. Testing Styles
        1. Traditional Testing
        2. Agile Testing
        3. BDD, ATDD, and Specification by Example
      4. Your Quality Assurance and Developer Testing
      5. Summary
    13. Chapter 3. The Testing Vocabulary
      1. Errors, Defects, Failures
      2. White Box and Black Box Testing
      3. Classifying Tests
        1. Test Levels
        2. Test Types
        3. Putting Test Levels and Types to Work
      4. The Agile Testing Quadrants
      5. Some Other Types of Testing
        1. Smoke Testing
        2. End-to-End Testing
        3. Characterization Testing
        4. Positive and Negative Testing
        5. Small, Medium, and Large Tests
      6. Summary
    14. Chapter 4. Testability from a Developer’s Perspective
      1. Testable Software
      2. Benefits of Testability
        1. Its Functionality Can Be Verified
        2. It Comes with Fewer Surprises
        3. It Can Be Changed
        4. Why Care about Testability
      3. Testability Defined
        1. Observability
        2. Controllability
        3. Smallness
        4. A Reminder about Testability
      4. Summary
    15. Chapter 5. Programming by Contract
      1. Contracts Formalize Constraints
        1. Contract Building Blocks
      2. Implementing Programming by Contract
        1. Thinking in Contracts
      3. Enforcing Contracts
        1. Assertions
        2. Libraries that Support Contracts
        3. Unit Tests
        4. Static Analysis
      4. Summary
    16. Chapter 6. Drivers of Testability
      1. Direct Input and Output
      2. Indirect Input and Output
      3. State
      4. Temporal Coupling
      5. Data Types and Testability
      6. Domain-to-Range Ratio
      7. Summary
    17. Chapter 7. Unit Testing
      1. Why Do It?
      2. What Is a Unit Test?
      3. The Life Cycle of a Unit Testing Framework
        1. Test Methods
        2. Test Initializers and Cleanups
        3. Constructors and Destructors
      4. Naming Tests
        1. Mandated by the Framework
        2. Behavior-driven Development Style
        3. Unit of Work, State under Test, Expected Behavior
        4. Picking a Naming Standard
      5. Structuring Tests
      6. Assertion Methods
        1. Types of Assertions
        2. How Many Assertions per Test?
        3. Verbosity of Assertions
        4. Asserting Equality
        5. Constraints and Matchers
      7. Testing Exceptions
      8. Behavior-driven Development–Style Frameworks
        1. Test Structure
        2. Naming Tests
        3. Matchers
      9. Summary
    18. Chapter 8. Specification-based Testing Techniques
      1. Equivalence Partitioning
      2. Boundary Value Analysis
      3. Edge Cases and Gotchas for Some Data Types
        1. Numbers
        2. Strings
        3. Dates and Time
        4. Collections
      4. State Transition Testing
      5. Decision Tables
      6. Summary
    19. Chapter 9. Dependencies
      1. Relations between Objects
        1. Passing in Collaborators
        2. Using Factory Methods
        3. Providing an External Factory or Builder
      2. System Resource Dependencies
        1. Files
        2. The System Clock
        3. Other System Resource Dependencies
      3. Dependencies between Layers
      4. Dependencies across Tiers
      5. Summary
    20. Chapter 10. Data-driven and Combinatorial Testing
      1. Parameterized Tests
      2. Theories
      3. Generative Testing
        1. Verifying the Results
      4. Combinatorial Testing
        1. Single-mode Faults
        2. Double-mode Faults
        3. Beyond Double-mode Faults and All Pairs
      5. Summary
    21. Chapter 11. Almost Unit Tests
      1. Examples
        1. Tests Using In-memory Databases
        2. Test-specific Mail Servers
        3. Tests Using Lightweight Containers
        4. Tests of Web Services
      2. Impact
      3. Summary
    22. Chapter 12. Test Doubles
      1. Stubs
        1. Stub Flexibility
        2. Stubbing to Get Rid of Side Effects
      2. Fakes
      3. Mock Objects
        1. Verifying Indirect Output
        2. Verifying Indirect Input Transformations
      4. Spies
      5. Dummies
      6. Verify State or Behavior?
        1. State Verification
        2. Behavior Verification
        3. The Arguments
      7. Summary
    23. Chapter 13. Mocking Frameworks
      1. Constructing Test Doubles
      2. Setting Expectations
        1. Stubbing
      3. Verifying Interactions
      4. Misuse, Overuse, and Other Pitfalls
        1. Oververifying
        2. Mocking Concrete Classes
        3. Mocking Value-holding Classes
        4. Mocks Returning Mocks
      5. Summary
    24. Chapter 14. Test-driven Development—Classic Style
      1. Test-driving a Simple Search Engine
        1. Test 1: Discovering the API
        2. Test 2: Happy Path
        3. Test 3: Searching in Multiple Documents
        4. Test 4: More Sophisticated Documents
        5. Test 5: Finding Words in Multiple Documents
        6. Test 6: Removing Duplicate Matches
        7. Test 7: Introducing Ranking
        8. Test 8: Ignoring Case
        9. Test 9: Dealing with Punctuation Marks
      2. Order of Tests
      3. Red- to Green-bar Strategies
      4. Challenges
        1. Our Code Can’t Be Tested
        2. Our Code Is Special
        3. Test-driven Development Isn’t Complete Testing
        4. Starting from Zero
      5. Test First or Test Last?
      6. Summary
    25. Chapter 15. Test-driven Development—Mockist Style
      1. A Different Approach
        1. Test-driving Customer Registration
        2. Adding More Tests
      2. Double-loop TDD
        1. Another Feedback Loop
      3. Summary
    26. Chapter 16. Duplication
      1. Why Duplication Is Bad
      2. Taking Advantage of Duplication
      3. Mechanical Duplication
        1. Copy and Paste
        2. Block Copy and Paste
        3. Constructor Copy and Paste
        4. Method Duplication
      4. Knowledge Duplication
        1. Similar Functionality in Different Methods
        2. Similar Functionality in Different Classes
        3. Competing Implementations
        4. Competing Domain Models
      5. Summary
    27. Chapter 17. Working with Test Code
      1. Commenting Tests
        1. Strategies for Comment Avoidance
      2. Deleting Tests
        1. Prime Candidates for Deletion
        2. Possible Candidates for Deletion
        3. Why It’s Important to Delete Tests
      3. Summary
    28. Chapter 18. Beyond Unit Testing
      1. Tests that Aren’t Unit Tests
        1. Tests Enclosed in Transactions
        2. Tests that Exercise a Service or a Component
        3. Tests that Interact with Other Systems
        4. Tests Running through the User Interface
        5. Tests that Invoke a System
        6. And There’s More
      2. Characteristics of Tests that Aren’t Unit Tests
        1. Complexity
        2. Stability
        3. Error Localization
        4. Performance
        5. Environmental Dependence
        6. Target Audience
      3. Pointers and Practices
        1. Test Independence
        2. Setup
        3. Verification
        4. Use of Test Doubles
      4. Deciding on a Developer Testing Strategy
      5. Summary
    29. Chapter 19. Test Ideas and Heuristics
      1. High-level Considerations
        1. Test Effectiveness
        2. Test Recipe
        3. Level of Abstraction and Detail
        4. Archetype
        5. Source of Truth
      2. Low-level Considerations
        1. Zero-one-many
        2. Nulls
        3. Ranges
        4. Collections
        5. Exceptions and Errors
        6. Numbers
        7. Strings
        8. Dates
      3. Summary
    30. Appendix A. Tools and Libraries
    31. Appendix B. Source Code
      1. Test Doubles
      2. Data-driven and Combinatorial Testing
      3. Test-driven Development
        1. JUnit Version
        2. Spock Version
      4. Beyond Unit Testing
    32. Bibliography
    33. Index
    34. Code Snippets