Test Driven Development for Embedded C

Book description

Another day without Test-Driven Development means more time wasted chasing bugs and watching your code deteriorate. You thought TDD was for someone else, but it's not! It's for you, the embedded C programmer. TDD helps you prevent defects and build software with a long useful life. This is the first book to teach the hows and whys of TDD for C programmers.

TDD is a modern programming practice C developers need to know. It's a different way to program---unit tests are written in a tight feedback loop with the production code, assuring your code does what you think. You get valuable feedback every few minutes. You find mistakes before they become bugs. You get early warning of design problems. You get immediate notification of side effect defects. You get to spend more time adding valuable features to your product.

James is one of the few experts in applying TDD to embedded C. With his 1.5 decades of training,coaching, and practicing TDD in C, C++, Java, and C# he will lead you from being a novice in TDD to using the techniques that few have mastered.

This book is full of code written for embedded C programmers. You don't just see the end product, you see code and tests evolve. James leads you through the thought process and decisions made each step of the way. You'll learn techniques for test-driving code right nextto the hardware, and you'll learn design principles and how to apply them to C to keep your code clean and flexible.

To run the examples in this book, you will need a C/C++ development environment on your machine, and the GNU GCC tool chain or Microsoft Visual Studio for C++ (some project conversion may be needed).

Publisher resources

View/Submit Errata

Table of contents

  1. Test-Driven Development for Embedded C
  2. For the Best Reading Experience...
  3. Table of Contents
  4. What People Are Saying About Test-Driven Development for Embedded C
  5. Foreword by Jack Ganssle
  6. Foreword by Robert C. Martin
  7. Acknowledgments
  8. Preface
    1. Who Is This Book For?
    2. How to Read This Book
    3. The Code in This Book
    4. Online Resources
  9. Chapter 1: Test-Driven Development
    1. Why Do We Need TDD?
    2. What Is Test-Driven Development?
    3. Physics of TDD
    4. The TDD Microcycle
    5. TDD Benefits
    6. Benefits for Embedded
  10. Part 1: Getting Started
  11. Chapter 2: Test-Driving Tools and Conventions
    1. What Is a Unit Test Harness?
    2. Unity: A C-Only Test Harness
    3. CppUTest: A C++ Unit Test Harness
    4. Unit Tests Can Crash
    5. The Four-Phase Test Pattern
    6. Where Are We?
    7. Put the Knowledge to Work
  12. Chapter 3: Starting a C Module
    1. Elements of a Testable C Module
    2. What Does an LED Driver Do?
    3. Write a Test List
    4. Writing the First Test
    5. Test-Drive the Interface Before the Internals
    6. Incremental Progress
    7. Test-Driven Developer State Machine
    8. Tests Are FIRST
    9. Where Are We?
    10. Put the Knowledge to Work
  13. Chapter 4: Testing Your Way to Done
    1. Grow the Solution from Simple Beginnings
    2. Keep the Code Clean—Refactor as You Go
    3. Repeat Until Done
    4. Take a Step Back Before Claiming Done
    5. Where Are We?
    6. Put the Knowledge to Work
  14. Chapter 5: Embedded TDD Strategy
    1. The Target Hardware Bottleneck
    2. Benefits of Dual-Targeting
    3. Risks of Dual-Target Testing
    4. The Embedded TDD Cycle
    5. Dual-Target Incompatibilities
    6. Testing with Hardware
    7. Slow Down to Go Fast
    8. Where Are We?
    9. Put the Knowledge to Work
  15. Chapter 6: Yeah, but...
    1. We Don’t Have Time
    2. Why Not Write Tests After the Code?
    3. We’ll Have to Maintain the Tests
    4. Unit Tests Don’t Find All the Bugs
    5. We Have a Long Build Time
    6. We Have Existing Code
    7. We Have Constrained Memory
    8. We Have to Interact with Hardware
    9. Why a C++ Test Harness for Testing C?
    10. Where Are We?
    11. Put the Knowledge to Work
  16. Part 2: Testing Modules with Collaborators
  17. Chapter 7: Introducing Test Doubles
    1. Collaborators
    2. Breaking Dependencies
    3. When to Use a Test Double
    4. Faking It in C, What’s Next
    5. Where Are We?
    6. Put the Knowledge to Work
  18. Chapter 8: Spying on the Production Code
    1. Light Scheduler Test List
    2. Dependencies on Hardware and OS
    3. Link-Time Substitution
    4. Spying on the Code Under Test
    5. Controlling the Clock
    6. Make It Work for None, Then One
    7. Make It Work for Many
    8. Where Are We?
    9. Put the Knowledge to Work
  19. Chapter 9: Runtime-Bound Test Doubles
    1. Testing Randomness
    2. Faking with a Function Pointer
    3. Surgically Inserted Spy
    4. Verifying Output with a Spy
    5. Where Are We?
    6. Put the Knowledge to Work
  20. Chapter 10: The Mock Object
    1. Flash Driver
    2. MockIO
    3. Test-Driving the Driver
    4. Simulating a Device Timeout
    5. Is It Worth It?
    6. Mocking with CppUMock
    7. Generating Mocks
    8. Where Are We?
    9. Put the Knowledge to Work
  21. Part 3: Design and Continuous Improvement
  22. Chapter 11: SOLID, Flexible, and Testable Designs
    1. SOLID Design Principles
    2. SOLID C Design Models
    3. Evolving Requirements and a Problem Design
    4. Improving the Design with Dynamic Interface
    5. More Flexibility with Per-Type Dynamic Interface
    6. How Much Design Is Enough?
    7. Where Are We?
    8. Put the Knowledge to Work
  23. Chapter 12: Refactoring
    1. Two Values of Software
    2. Three Critical Skills
    3. Code Smells and How to Improve Them
    4. Transforming the Code
    5. But What About Performance and Size?
    6. Where Are We?
    7. Put the Knowledge to Work
  24. Chapter 13: Adding Tests to Legacy Code
    1. Legacy Code Change Policy
    2. Boy Scout Principle
    3. Legacy Change Algorithm
    4. Test Points
    5. Two-Stage struct Initialization
    6. Crash to Pass
    7. Characterization Tests
    8. Learning Tests for Third-Party Code
    9. Test-Driven Bug Fixes
    10. Add Strategic Tests
    11. Where Are We?
    12. Put the Knowledge to Work
  25. Chapter 14: Test Patterns and Antipatterns
    1. Ramble-on Test Antipattern
    2. Copy-Paste-Tweak-Repeat Antipattern
    3. Sore Thumb Test Cases Antipattern
    4. Duplication Between Test Groups Antipattern
    5. Test Disrespect Antipattern
    6. Behavior-Driven Development Test Pattern
    7. Where Are We?
    8. Put the Knowledge to Work
  26. Chapter 15: Closing Thoughts
  27. Part 4: Appendixes
  28. Appendix 1: Development System Test Environment
    1. Development System Tool Chain
    2. Full Test Build makefile
    3. Smaller Test Builds
  29. Appendix 2: Unity Quick Reference
    1. Unity Test File
    2. Unity Test main
    3. Unity TEST Condition Checks
    4. Command-Line Options
    5. Unity in Your Target
  30. Appendix 3: CppUTest Quick Reference
    1. The CppUTest Test File
    2. Test Main
    3. TEST Condition Checks
    4. Test Execution Order
    5. Scripts to Create Starter Files
    6. CppUTest in Your Target
    7. Convert CppUTest Tests to Unity
  31. Appendix 4: LedDriver After Getting Started
    1. LedDriver First Few Tests in Unity
    2. LedDriver First Few Tests in CppUTest
    3. LedDriver Early Interface
    4. LedDriver Skeletal Implementation
  32. Appendix 5: Example OS Isolation Layer
    1. Test Cases to Assure Substitutable Behavior
    2. POSIX Implementation
    3. Micrium RTOS Implementation
    4. Win32 Implementation
    5. Burden the Layer, Not the Application
  33. Appendix 6: Bibliography
    1. You May Be Interested In…

Product information

  • Title: Test Driven Development for Embedded C
  • Author(s): James W. Grenning
  • Release date: April 2011
  • Publisher(s): Pragmatic Bookshelf
  • ISBN: 9781680504880