-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3 from christopherkinyua/chris/create-create-unit…
…-test-framework-i2 Create create unit test framework
- Loading branch information
Showing
12 changed files
with
302 additions
and
39 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
# C Unit Tests | ||
|
||
This repo uses an in-house unit test framework, which is about as minimal as unit tests can be. | ||
|
||
## How to Write a Test | ||
|
||
The following guide demonstrates an example of creating a testable function, and then writing | ||
unit tests for that function. | ||
|
||
1. Come up with a testable function (called the Function-Under-Test, or FUT). For examples: | ||
|
||
```c | ||
// File: transforms/byte_transforms.c | ||
|
||
#include "transforms/byte_transforms.h" | ||
|
||
uint32_t GEN_convert_big_endian_four_byte_array_to_uint32(uint8_t four_byte_array[]) { | ||
// recall: big endian means the Most Significant Bit (MSB) is at index 0 (left side) | ||
return (four_byte_array[0] << 24) | (four_byte_array[1] << 16) | | ||
(four_byte_array[2] << 8) | four_byte_array[3]; | ||
} | ||
``` | ||
|
||
2. Create a new file in `Core/Src/unit_tests` called `test_bytes_transforms.c`. Create the unit test | ||
function within that file: | ||
|
||
```c | ||
// File: unit_tests/test_bytes_transforms.c | ||
|
||
#include "unit_tests/unit_test_helpers.h" // for all unit tests | ||
#include "transforms/byte_transforms.h" // for the Function-Under-Test | ||
|
||
uint8_t TEST_EXEC__GEN_convert_big_endian_four_byte_array_to_uint32() { | ||
// TODO: implement unit test later | ||
TEST_ASSERT_TRUE(1 == 1); | ||
|
||
return 0; // THIS LINE MUST BE INCLUDED to indicate the test passed | ||
} | ||
``` | ||
|
||
3. Add the function prototype to the header file `Core/Inc/unit_tests/test_bytes_transforms.h`: | ||
|
||
```c | ||
// File: unit_tests/test_bytes_transforms.h | ||
// ... | ||
uint8_t TEST_EXEC__GEN_convert_big_endian_four_byte_array_to_uint32(); | ||
// ... | ||
``` | ||
|
||
4. Add the test to the "inventory table" of tests in `Core/Src/unit_tests/unit_test_inventory.c`: | ||
|
||
```c | ||
// File: unit_tests/unit_test_inventory.c | ||
#include "unit_tests/test_byte_transforms.h" | ||
|
||
const TEST_Definition_t TEST_definitions[] = { | ||
// ... | ||
// Add the following section: | ||
{ | ||
.test_func = TEST_EXEC__GEN_convert_big_endian_four_byte_array_to_uint32, | ||
.test_file = "transforms/byte_transforms", | ||
.test_func_name = "GEN_convert_big_endian_four_byte_array_to_uint32" | ||
}, | ||
// ... | ||
}; | ||
|
||
``` | ||
|
||
5. Flash the ESP32, and check the monitor ESP-IDF Monitor window. See that the test passes. | ||
|
||
6. Go back to the `TEST_EXEC__GEN_convert_big_endian_four_byte_array_to_uint32` function, and implement | ||
the test: | ||
|
||
```c | ||
// File: unit_tests/test_bytes_transforms.c | ||
|
||
uint8_t TEST_EXEC__GEN_convert_big_endian_four_byte_array_to_uint32() { | ||
uint8_t test_array_1[4] = {0x12, 0x34, 0x56, 0x78}; | ||
uint32_t expected_result_1 = 0x12345678; | ||
TEST_ASSERT_TRUE(GEN_convert_big_endian_four_byte_array_to_uint32(test_array_1) == expected_result_1); | ||
|
||
uint8_t test_array_2[4] = {0xFE, 0xDC, 0xBA, 0x98}; | ||
uint32_t expected_result_2 = 4275878552; // 0xFEDCBA98 | ||
TEST_ASSERT_TRUE(GEN_convert_big_endian_four_byte_array_to_uint32(test_array_2) == expected_result_2); | ||
|
||
return 0; // THIS LINE MUST BE INCLUDED to indicate the test passed | ||
} | ||
``` | ||
|
||
7. Run the test again. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,11 @@ | ||
# Define the source and include directories | ||
set(INCLUDE_DIRS Inc) | ||
set(INCLUDE_DIRS Inc Inc/unit_tests) | ||
set(SRC_DIR Src) | ||
|
||
# Automatically include all .c files in src | ||
file(GLOB SRC_FILES "${SRC_DIR}/*.c") | ||
# Automatically include all .c files in Core/Src and Core/Src/unit_tests | ||
file(GLOB SRC_FILES "${SRC_DIR}/*.c" "${SRC_DIR}/unit_tests/*.c") | ||
|
||
# Register the component with ESP-IDF | ||
idf_component_register(SRCS ${SRC_FILES} | ||
INCLUDE_DIRS ${INCLUDE_DIRS} | ||
REQUIRES driver) | ||
REQUIRES driver esp_timer) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
#ifndef __INCLUDE_GUARD__UNIT_TEST_EXECUTOR_H__ | ||
#define __INCLUDE_GUARD__UNIT_TEST_EXECUTOR_H__ | ||
|
||
#include "main.h" | ||
|
||
#include "unit_test_inventory.h" | ||
|
||
uint8_t TEST_run_all_unit_tests_and_log(char log_buffer[], uint16_t log_buffer_size); | ||
|
||
#endif // __INCLUDE_GUARD__UNIT_TEST_EXECUTOR_H__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
#ifndef __INCLUDE_GUARD__UNIT_TEST_HELPERS_H__ | ||
#define __INCLUDE_GUARD__UNIT_TEST_HELPERS_H__ | ||
|
||
#define TEST_ASSERT(x) if (!(x)) { return 1; } | ||
#define TEST_ASSERT_TRUE(x) if (!(x)) { return 1; } | ||
#define TEST_ASSERT_FALSE(x) if ((x)) { return 1; } | ||
|
||
#endif // __INCLUDE_GUARD__UNIT_TEST_HELPERS_H__ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
#ifndef __INCLUDE_GUARD__UNIT_TEST_INVENTORY_H__ | ||
#define __INCLUDE_GUARD__UNIT_TEST_INVENTORY_H__ | ||
|
||
#include <stdint.h> | ||
|
||
typedef uint8_t (*TEST_Function_Ptr)(); | ||
|
||
typedef struct { | ||
TEST_Function_Ptr test_func; | ||
char* test_file; | ||
char* test_func_name; | ||
} TEST_Definition_t; | ||
|
||
|
||
extern const TEST_Definition_t TEST_definitions[]; | ||
extern const int16_t TEST_definitions_count; | ||
|
||
|
||
#endif // __INCLUDE_GUARD__UNIT_TEST_INVENTORY_H__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
#ifndef __INCLUDE_GUARD__UNIT_TEST_PWM_H__ | ||
#define __INCLUDE_GUARD__UNIT_TEST_PWM_H__ | ||
|
||
#include <stdint.h> | ||
|
||
uint8_t TEST_EXEC__LED_set_dimming(); | ||
|
||
#endif // __INCLUDE_GUARD__UNIT_TEST_PWM_H__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
#include "unit_tests/unit_test_executor.h" | ||
#include "unit_tests/unit_test_inventory.h" | ||
|
||
#include "main.h" | ||
|
||
#include "string.h" | ||
#include "stdio.h" | ||
#include "esp_timer.h" | ||
|
||
uint8_t TEST_run_all_unit_tests_and_log(char log_buffer[], uint16_t log_buffer_size) | ||
{ | ||
uint16_t total_exec_count = 0; | ||
uint16_t total_pass_count = 0; | ||
uint16_t total_fail_count = 0; | ||
const uint32_t start_time_ms = esp_timer_get_time() / 1000; | ||
|
||
log_buffer[0] = '\0'; | ||
|
||
for (uint8_t test_num = 0; test_num < TEST_definitions_count; test_num++) | ||
{ | ||
TEST_Function_Ptr test_function = TEST_definitions[test_num].test_func; | ||
uint8_t result = test_function(); | ||
|
||
char test_log_buffer[200]; | ||
snprintf( | ||
test_log_buffer, | ||
sizeof(test_log_buffer), | ||
"Test #%03d: %s (%s > %s)\n", | ||
test_num, | ||
(result == 0) ? "PASS ✅" : "FAIL ❌", | ||
TEST_definitions[test_num].test_file, | ||
TEST_definitions[test_num].test_func_name); | ||
printf(test_log_buffer); | ||
|
||
total_exec_count++; | ||
if (result == 0) | ||
{ | ||
total_pass_count++; | ||
} | ||
else | ||
{ | ||
total_fail_count++; | ||
} | ||
} | ||
const uint32_t end_time_ms = esp_timer_get_time() / 1000; | ||
|
||
snprintf( | ||
log_buffer, | ||
log_buffer_size, | ||
"Total tests: %d - Pass: %d, Fail: %d, Duration: %lums", | ||
total_exec_count, | ||
total_pass_count, | ||
total_fail_count, | ||
end_time_ms - start_time_ms); | ||
|
||
return total_fail_count == 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#include "unit_tests/unit_test_helpers.h" | ||
#include "unit_tests/unit_test_inventory.h" | ||
#include "unit_tests/unit_test_pwm.h" | ||
|
||
// extern | ||
const TEST_Definition_t TEST_definitions[] = { | ||
|
||
{.test_func = TEST_EXEC__LED_set_dimming, | ||
.test_file = "unit_tests/unit_test_pwm", | ||
.test_func_name = "LED_set_dimming"}, | ||
|
||
}; | ||
|
||
// extern | ||
const int16_t TEST_definitions_count = sizeof(TEST_definitions) / sizeof(TEST_Definition_t); |
Oops, something went wrong.