This repo uses an in-house unit test framework, which is about as minimal as unit tests can be.
Why?
The intentions with these unit tests are:
- Force structuring of functions in ways such that unit tests can be written for them.
- Come up with tests cases from documentation/experimenting before implementing functions (test-driven development).
- Provide a way to ensure core functionality continues working in the wake of refactors and configuration changes.
Non-Objectives
Companies may care about the following, but we do not:
- Seeking high coverage of unit tests, or enforcing creating unit tests where there is minimal gain.
- Using mocks to emulate difficult-to-test systems.
- Instead: write functions in a way that the testable part and the difficult-to-test system never appear in the same function. For example, implement reading from UART in a different function than the parser.
Unit tests, when used correctly, are extremely powerful, and enable far faster development.
How to Write a Test
The following guide demonstrates an example of creating a testable function, and then writing unit tests for that function.
To see the complete diff of implementing this test, look at commit a1943af.
- Install the Codeium extension for VS Code, and sign in. This AI code generation tool will help generate a lot of the boilerplate code you're about to encounter.
Come up with a testable function (called the Function-Under-Test, or FUT). For examples:
return (four_byte_array[0] << 24) | (four_byte_array[1] << 16) |
(four_byte_array[2] << 8) | four_byte_array[3];
}
Create a new file in Core/Src/unit_tests
called test_bytes_transforms.c
. Create the unit test function within that file:
return 0;
}
#define TEST_ASSERT_TRUE(x)
Definition unit_test_helpers.h:6
Add the function prototype to the header file Core/Inc/unit_tests/test_bytes_transforms.h
:
Add the test to the "inventory table" of tests in Core/Src/unit_tests/unit_test_inventory.c
:
{
.test_file = "transforms/byte_transforms",
.test_func_name = "GEN_convert_big_endian_four_byte_array_to_uint32"
},
};
Definition unit_test_inventory.h:10
const TEST_Definition_t TEST_definitions[]
Definition unit_test_inventory.c:23
- Flash the STM32, and run the
CTS1+run_all_unit_tests
command via the Debug UART line. See that the test passes.
Go back to the TEST_EXEC__GEN_convert_big_endian_four_byte_array_to_uint32
function, and implement the test:
uint8_t test_array_1[4] = {0x12, 0x34, 0x56, 0x78};
uint32_t expected_result_1 = 0x12345678;
uint8_t test_array_2[4] = {0xFE, 0xDC, 0xBA, 0x98};
uint32_t expected_result_2 = 4275878552;
return 0;
}
- Run the test again.