Testing Your Embedded Rust (feat. embedded-hal-mock and explosions)
Let's say we have a device - it's a simple bounce-back machine. When you send a beep, it replies with a boop. This device is the Beep-Boop Box! 📦✨
In Rust, using embedded-hal
, we've connected to this machine and written a generic driver for it. Here's how it might look:
Oh no! It seems that we accidentally wrote to SPI twice. However, our device doesn't say what it'll do if that happens, nor does our program. There's no way for us to know!
Let's pretend we didn't catch the error, though. Maybe no one found this bug, setting many Beep-Boop Boxes on fire! That's scary.
Mocking Our Device
However, we don't have to wait for customers' systems to set on fire! embedded-hal
has a testing suite lovingly known as embedded-hal-mock
. It supports both 0.x and 1.x versions of embedded-hal
, so practically everyone can use it!
Its README describes the crate's goal best:
"The goal of the crate is to be able to test drivers in CI without having access to hardware." ~the
embedded-hal-mock
people
embedded-hal-mock
does precisely that! By modeling each action you perform over SPI, I2C, etc., you can ensure that only the operations you expect to happen... happen. Each action is known as a Transaction
. You can read more in its documentation.
Thankfully, with this crate, we can express exactly what responses we expect to send and receive given some combination of IO. Let's take a look!
//! Tests module
use ;
Writing this code "for real," I carefully ran the test...
As you can see, the test caught the issue! We only asked the mock
to expect two operations: read and write. However, it found a second read instead. In the model we've created, that's always a no-no. 👋
Let's say we fixed the bug - how does our test feel now? 😳
We're golden! Our Beep-Boop customers are safe! I've used it in my crates, too, helping to ensure that nothing goes wrong without my CI (and thus, me) knowing!
This crate can supercharge your embedded Rust - notably when used alongside something like defmt-test
for your binaries!
Wrapping Up
As you can see, some of Rust's biggest strengths lie in its testing mechanics. Imagining how a device might work when writing a driver can be challenging. Luckily, with Rust, someone's always got your back. In this case, that's you!
If you haven't tried embedded Rust, I wholeheartedly recommend it. 🦀✨
What do you think about these tools? Have you used them in your projects, or am I missing something in the article? Please let me know with a GitHub issue or via email!
Thanks for taking a look - good luck!