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