contents
foreword
preface
acknowledgments
about this book
about the cover illustration
Part 1 Getting started
- 1 The basics of unit testing
- 1.1 Unit testing—the classic definition
- 1.2 Properties of a good unit test
- 1.3 Integration tests
- 1.4 Good unit test—a definition
- 1.5 A simple unit test example
- 1.6 Test-driven development
- 1.7 Summary
- 2 A first unit test
- 2.1 Frameworks for unit testing
- 2.2 Introducing the LogAn project
- 2.3 First steps with NUnit
- 2.4 Writing our first test
- 2.5 More NUnit attributes
- 2.6 Indirect testing of state
- 2.7 Summary
Part 2 Core techniques
- 3 Using stubs to break dependencies
- 3.1 Introducing stubs
- 3.2 Identifying a filesystem dependency in LogAn
- 3.3 Determining how to easily test LogAnalyzer
- 3.4 Refactoring our design to be more testable
- 3.5 Variations on refactoring techniques
- 3.6 Using Extract and Override to create stub results
- 3.7 Overcoming the encapsulation problem
- 3.8 Summary
- 4 Interaction testing using mock objects
- 4.1 State-based versus interaction testing
- 4.2 The difference between mocks and stubs
- 4.3 A simple manual mock example
- 4.4 Using a mock and a stub together
- 4.5 One mock per test
- 4.6 Stub chains: stubs that produce mocks or other stubs
- 4.7 The problems with handwritten mocks and stubs
- 4.8 Summary
- 5 Isolation (mock object) frameworks
- 5.1 Why use isolation frameworks?
- 5.2 Dynamically creating a fake object
- 5.3 Strict versus nonstrict mock objects
- 5.4 Returning values from fake objects
- 5.5 Creating smart stubs with an isolation framework
- 5.6 Parameter constraints for mocks and stubs
- 5.7 Testing for event-related activities
- 5.8 Arrange-act-assert syntax for isolation
- 5.9 Current isolation frameworks for .NET
- 5.10 Advantages of isolation frameworks
- 5.11 Traps to avoid when using isolation frameworks
- 5.12 Summary
Part 3 The test code
- 6 Test hierarchies and organization
- 6.1 Having automated builds run automated tests
- 6.2 Mapping out tests based on speed and type
- 6.3 Ensuring tests are part of source control
- 6.4 Mapping test classes to code under test
- 6.5 Building a test API for your application
- 6.6 Summary
- 7 The pillars of good tests
- 7.1 Writing trustworthy tests
- 7.2 Writing maintainable tests
- 7.3 Writing readable tests
- 7.4 Summary
Part 4 Design and process
- 8 Integrating unit testing into the organization
- 8.1 Steps to becoming an agent of change
- 8.2 Ways to succeed
- 8.3 Ways to fail
- 8.4 Tough questions and answers
- 8.5 Summary
- 9 Working with legacy code
- 9.1 Where do you start adding tests?
- 9.2 Choosing a selection strategy
- 9.3 Writing integration tests before refactoring
- 9.4 Important tools for legacy code unit testing
- 9.5 Summary
- Appendix A : Design and testability
- Appendix B : Extra tools and frameworks
- Index