测试¶
Nexus uses Google Test for unit testing and provides comprehensive testing infrastructure for embedded software development.
测试框架¶
Unit Testing: Google Test (gtest)
Mocking: Google Mock (gmock)
Coverage: gcov/lcov
Static Analysis: MISRA C checker
Building Tests¶
启用测试进行配置和构建:
CMake -B build -DNEXUS_PLATFORM=native -DNEXUS_BUILD_TESTS=ON
CMake --build build --config Release
运行测试¶
Run All Tests¶
ctest --test-dir build -C Release --output-on-failure
Run Specific Test Suite¶
./build/tests/Release/nexus_tests --gtest_filter="HalGpioTest.*"
使用详细输出运行¶
./build/tests/Release/nexus_tests --gtest_filter="*" --gtest_print_time=1
List Available Tests¶
./build/tests/Release/nexus_tests --gtest_list_tests
编写测试¶
测试 File Location¶
将测试文件放在 tests/ 目录中,结构如下:
tests/
├── hal/
│ ├── test_hal_gpio.cpp
│ ├── test_hal_uart.cpp
│ └── test_hal_spi.cpp
├── osal/
│ ├── test_osal_task.cpp
│ ├── test_osal_mutex.cpp
│ └── test_osal_queue.cpp
└── framework/
└── log/
└── test_log.cpp
测试 File Template¶
/**
* \file test_hal_gpio.cpp
* \brief HAL GPIO unit tests
*/
#include <gtest/gtest.h>
extern "C" {
#include "hal/hal_gpio.h"
}
class HalGpioTest : public ::testing::Test {
protected:
void SetUp() override {
/* Initialize test fixtures */
}
void TearDown() override {
/* Clean up test fixtures */
}
};
TEST_F(HalGpioTest, InitOutput) {
hal_gpio_config_t config = {
.direction = HAL_GPIO_DIR_OUTPUT,
.pull = HAL_GPIO_PULL_NONE,
.output_mode = HAL_GPIO_OUTPUT_PP,
.speed = HAL_GPIO_SPEED_LOW,
.init_level = HAL_GPIO_LEVEL_LOW
};
EXPECT_EQ(HAL_OK, hal_gpio_init(HAL_GPIO_PORT_A, 0, &config));
}
TEST_F(HalGpioTest, InitNullConfig) {
EXPECT_EQ(HAL_ERROR_NULL_POINTER,
hal_gpio_init(HAL_GPIO_PORT_A, 0, nullptr));
}
TEST_F(HalGpioTest, WriteOutput) {
/* Setup */
hal_gpio_config_t config = {
.direction = HAL_GPIO_DIR_OUTPUT
};
hal_gpio_init(HAL_GPIO_PORT_A, 0, &config);
/* Test */
EXPECT_EQ(HAL_OK, hal_gpio_write(HAL_GPIO_PORT_A, 0, HAL_GPIO_LEVEL_HIGH));
}
测试 Naming Convention¶
Test class:
ModuleNameTest(e.g.,HalGpioTest,OsalMutexTest)Test case: Descriptive action (e.g.,
InitOutput,WriteInvalidPort)
Test Categories¶
Positive Tests: Verify correct behavior with valid inputs
Negative Tests: Verify error handling with invalid inputs
Boundary Tests: Test edge cases and limits
Integration Tests: Test component interactions
Code Coverage¶
Enable Coverage¶
CMake -B build -DNEXUS_PLATFORM=native -DNEXUS_BUILD_TESTS=ON -DNEXUS_ENABLE_COVERAGE=ON CMake --build build
生成覆盖率报告¶
cd build ctest --output-on-failure lcov --capture --directory . --output-file coverage.info lcov --remove coverage.info '/usr/*' '*/tests/*' --output-file coverage.info genhtml coverage.info --output-directory coverage_report
Coverage 要求¶
最低代码覆盖率:90%
所有公共 API 必须有测试
所有错误路径必须经过测试
静态分析¶
MISRA C 合规性¶
Run MISRA C checker:
# Using cppcheck with MISRA addon
cppcheck --addon=misra hal/ osal/ framework/
地址消毒器¶
使用消毒器构建以检测内存错误:
CMake -B build -DNEXUS_PLATFORM=native -DNEXUS_BUILD_TESTS=ON \
-DCMAKE_C_FLAGS="-fsanitize=address -fno-omit-frame-pointer" \
-DCMAKE_CXX_FLAGS="-fsanitize=address -fno-omit-frame-pointer"
最佳实践¶
Test Independence: Each test should be independent and not rely on other tests
Clear Assertions: Use descriptive assertion messages
Setup/Teardown: Use fixtures for common setup and cleanup
Mock External Dependencies: Use mocks for hardware and OS dependencies
Test Edge Cases: Include boundary conditions and error cases
Keep Tests Fast: Unit tests should run quickly
Avoid Test Duplication: Use parameterized tests for similar cases
参数化测试¶
class HalGpioPortTest : public ::testing::TestWithParam<hal_gpio_port_t> {};
TEST_P(HalGpioPortTest, InitValidPort) {
hal_gpio_port_t port = GetParam();
hal_gpio_config_t config = { .direction = HAL_GPIO_DIR_OUTPUT };
EXPECT_EQ(HAL_OK, hal_gpio_init(port, 0, &config));
}
INSTANTIATE_TEST_SUITE_P(
AllPorts,
HalGpioPortTest,
::testing::Values(
HAL_GPIO_PORT_A,
HAL_GPIO_PORT_B,
HAL_GPIO_PORT_C
)
);
CI Integration¶
测试通过 GitHub Actions 在每个 PR 上自动运行:
Multi-platform testing (Windows, Linux, macOS)
覆盖率报告
内存消毒器检查
MISRA compliance checks