defmt-test

a test harness for embedded devices

Basic usage

  1. If you don't have a project setup yet, start from the [app-template], then proceed with step 3. If you have a project based on an old version of app-template then proceed with step 1.

  2. In the testsuite crate, add defmt-test to the dependencies:

``` diff # testsuite/Cargo.toml

[dependencies] + defmt-test = "0.1.0" ```

  1. Within the testsuite/tests/test.rs file, create a tests module and mark it with the #[defmt_test::tests] attribute. Within that module write std-like unit tests: functions marked with the #[test] attribute.

``` rust // testsuite/tests/test.rs

[defmt_test::tests]

mod tests { #[test] fn assert_true() { assert!(true) }

#[test]
fn assert_false() {
    assert!(false, "TODO: write actual tests")
}

} ```

  1. Run cargo test -p testsuite to run the unit tests

console $ cargo test -p testsuite (..) 0.000000 INFO running assert_true .. └─ test::tests::__defmt_test_entry @ tests/test.rs:7 0.000001 INFO .. assert_true ok └─ test::tests::__defmt_test_entry @ tests/test.rs:7 0.000002 INFO running assert_false .. └─ test::tests::__defmt_test_entry @ tests/test.rs:7 0.000003 ERROR panicked at 'TODO: write actual tests', testsuite/tests/test.rs:16:9 └─ panic_probe::print_defmt::print @ (..omitted..) stack backtrace: 0: HardFaultTrampoline <exception entry> 1: __udf 2: cortex_m::asm::udf at (..omitted..) 3: rust_begin_unwind at (..omitted..) 4: core::panicking::panic_fmt at (..omitted..) 5: core::panicking::panic at (..omitted..) 6: test::tests::assert_false at tests/test.rs:16 7: main at tests/test.rs:7 8: ResetTrampoline at (..omitted..) 9: Reset at (..omitted..)

NOTE unit tests will be executed sequentially

Adding state

An #[init] function can be written within the #[tests] module. This function will be executed before all unit tests and its return value, the test suite state, can be passed to unit tests as an argument.

``` rust // state shared across unit tests struct MyState { flag: bool, }

[defmt_test::tests]

mod tests { #[init] fn init() -> super::MyState { // state initial value super::MyState { flag: true, } }

// this unit test doesn't access the state
#[test]
fn assert_true() {
    assert!(true);
}

// but this test does
#[test]
fn assert_flag(state: &mut super::MyState) {
    assert!(state.flag)
}

} ```

console $ cargo test -p testsuite 0.000000 INFO running assert_true .. └─ test::tests::__defmt_test_entry @ tests/test.rs:11 0.000001 INFO .. assert_true ok └─ test::tests::__defmt_test_entry @ tests/test.rs:11 0.000002 INFO running assert_flag .. └─ test::tests::__defmt_test_entry @ tests/test.rs:11 0.000003 INFO .. assert_flag ok └─ test::tests::__defmt_test_entry @ tests/test.rs:11

Support

defmt-test is part of the [Knurling] project, [Ferrous Systems]' effort at improving tooling used to develop for embedded systems.

If you think that our work is useful, consider sponsoring it via [GitHub Sponsors].

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be licensed as above, without any additional terms or conditions.