测试

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

  1. Positive Tests: Verify correct behavior with valid inputs

  2. Negative Tests: Verify error handling with invalid inputs

  3. Boundary Tests: Test edge cases and limits

  4. 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"

最佳实践

  1. Test Independence: Each test should be independent and not rely on other tests

  2. Clear Assertions: Use descriptive assertion messages

  3. Setup/Teardown: Use fixtures for common setup and cleanup

  4. Mock External Dependencies: Use mocks for hardware and OS dependencies

  5. Test Edge Cases: Include boundary conditions and error cases

  6. Keep Tests Fast: Unit tests should run quickly

  7. 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