Intro to Embedded Rust Part 9: Test-Driven Development | DigiKey
In this video, we cover test-driven development (TDD) for embedded Rust by demonstrating writing a unit test for our previous TMP102 temperature sensor driver library (crate) and a simulated I2C bus known as a “stub.” The written guide for this episode can be found here: https://www.digikey.com/en/maker/tutorials/2026/intro-to-embedded-rust-part-9-test-driven-development The GitHub repository containing the Docker image and example code for this series can be found here: https://github.com/ShawnHymel/introduction-to-embedded-rust Test-driven development is a professional software methodology where you write tests before implementing functionality, helping catch bugs early and ensuring code meets requirements. While TDD is common in application development, it presents unique challenges in embedded systems where code runs on hardware and interacts with peripherals like I2C, SPI, and GPIO. See here to learn more about Continuous Integration/Continuous Delivery (CI/CD): https://www.youtube.com/watch?v=1nxGcfIm-TU&list=PLEBQazB0HUyR00bgoctk-5uZoOrbmPASC This tutorial demonstrates how to write unit tests for our TMP102 temperature sensor driver that run entirely on your development computer without requiring a Raspberry Pi Pico 2, sensor hardware, or any embedded target. You'll learn how to create stub implementations of embedded-hal traits, use Rust's testing framework with cargo test, and apply TDD principles to embedded driver development for reliable, maintainable code. This hands-on embedded testing tutorial covers the complete TDD workflow and testing concepts essential for professional development. We explain the red-green-blue cycle: writing failing tests first (red phase), implementing code to make tests pass (green phase), and refactoring for quality (blue phase). We cover the three levels of testing: unit tests for individual functions, integration tests for component interaction, and system/end-to-end tests for complete applications. We also define common test substitution terminology including dummies (placeholders), fakes (working but simplified implementations), stubs (predetermined responses), spies (recording call information), and mocks (verifying correct usage). We focus on using stubs and dummies to simulate I2C communication without real hardware, enabling fast, automated testing during development. We put these concepts into practice with a demonstration: creating a test infrastructure for the TMP102 driver library along with two unit tests. We cover how to use the #[cfg(test)] attribute to include test-only code that doesn't compile into production builds, and how to access the standard library for testing while keeping your library no_std for embedded targets. We build an I2cStub struct that implements the embedded_hal::i2c::I2c trait with configurable responses, allowing you to set predetermined temperature values and verify driver behavior. You'll see how to write test functions with #[test] attributes, use assertions like assert_eq! to verify behavior, and run tests with cargo test command.