You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ceedling中使用ASSERT语句进行单元测试时断言失败问题排查

问题排查:Ceedling测试AD7606C初始化函数时断言失败及执行异常

被测函数代码

fsp_err_t ad7606c_init(const bsp_io_port_pin_t cs, const spi_instance_t* spi)
{
    fsp_err_t result = FSP_SUCCESS;
    uint8_t rx[20] = {0};

    /* write config reg use 1 d out line */
    volatile ad7606c_config_reg_t config = {.DOUT_FORMAT = 0};
    write_reg(cs, spi, AD7606C_REG_CONFIG, config.REG);
    /* read config reg */
    read_reg(cs, spi, AD7606C_REG_CONFIG, 1, rx);

    /* read id reg */
    read_reg(cs, spi, AD7606C_REG_ID, 1, rx);
    /* id must be 0x32 */
    assert(rx[1] == ID);

    /* write range reg */
    volatile ad7606c_range_reg_t range = {.CH1_RANGE = AD7606C_RANGE_12500M_TO_12500P_DIFF, .CH2_RANGE = AD7606C_RANGE_12500M_TO_12500P_DIFF};
    write_reg(cs, spi, AD7606C_REG_RANGE_CH1_CH2, range.REG);
    write_reg(cs, spi, AD7606C_REG_RANGE_CH3_CH4, range.REG);
    write_reg(cs, spi, AD7606C_REG_RANGE_CH5_CH6, range.REG);
    write_reg(cs, spi, AD7606C_REG_RANGE_CH7_CH8, range.REG);

#ifdef INTERFACE_CHECK 
    write_reg(cs, spi, AD7606C_REG_DIGITAL_DIAG_ENA, 0x81);
#endif

    return result;
}

测试报错信息

ERROR: Test executable "test_ad7606c.out" failed.
Produced no final test result counts in $stdout:
Assertion failed: rx[1] == ID, file src/ad7606c/ad7606c.c, line 59

62:test_ad7606c_init_normal_initialization:PASS

And exited with status: [0] (count of failed tests).
This is often a symptom of a bad memory access in source or test code.

辅助断言支持头文件

#ifndef ASSERT_UNIT_TEST_SUPPORT_H_
#define ASSERT_UNIT_TEST_SUPPORT_H_

#include "CException.h"

#define TEST_ASSERT_FAIL_ASSERT(_code_under_test)         \
{                                                         \
  CEXCEPTION_T e;                                         \
  Try {                                                   \
    _code_under_test;                                     \
    TEST_FAIL_MESSAGE("Code under test did not assert");  \
  } Catch(e) {}                                           \
}

#define TEST_ASSERT_PASS_ASSERT(_code_under_test)               \
{                                                              \
  CEXCEPTION_T e;                                               \
  Try {                                                         \
    _code_under_test;                                           \
  } Catch(e) {                                                 \
    TEST_FAIL_MESSAGE("Code under test failed an assertion");   \
  }                                                              \
}

#endif

测试用例代码

#include "unity.h"
#include "r_spi_api.h"   
#include "bsp_io.h"
#include "ad7606c.h"
#include "Helper.h"
#include "mock_regread.h"

// Definitions for testing
#define CS_PIN 1                    // Chip select pin mock value
#define SPI_INSTANCE NULL           // SPI instance mock (assuming a null pointer for simplicity)

void test_ad7606c_init_id_mismatch(void)
{
    uint8_t rx[20] = {0};
    rx[1] = 0x00; // Incorrect ID value

    // Expected sequence
    write_reg_Expect(CS_PIN, SPI_INSTANCE, AD7606C_REG_CONFIG, 0);
    read_reg_Expect(CS_PIN, SPI_INSTANCE, AD7606C_REG_CONFIG, 1, rx);
    read_reg_Expect(CS_PIN, SPI_INSTANCE, AD7606C_REG_ID, 1, rx);

    // Call the function and expect assertion failure
    TEST_ASSERT_FAIL_ASSERT(ad7606c_init(CS_PIN, SPI_INSTANCE));
}

排查与解决步骤

1. 替换原生assert为异常抛出宏

标准库的assert会直接调用abort()终止程序,导致Ceedling无法捕获测试结果,必须替换成能抛出CException的版本:
在测试环境的头文件(比如ad7606c.h或专门的测试配置头文件)中添加:

#ifdef TEST
#include "CException.h"
#define assert(expr) do { if (!(expr)) Throw(1); } while(0)
#else
#include <assert.h>
#endif

确保编译测试代码时定义了TEST宏(可在Ceedling的project.yml中配置:defines: - TEST)。

2. 修正Mock函数的参数处理

被测函数中的rx是局部变量,测试用例中定义的rx无法直接传递给被测函数。需要用CMock的输出参数设置功能,让read_reg的mock实现将测试用例中预设的错误ID写入被测函数的rx数组:
修改测试用例中的mock调用:

void test_ad7606c_init_id_mismatch(void)
{
    uint8_t rx_id_mismatch[20] = {0};
    rx_id_mismatch[1] = 0x00; // Incorrect ID value

    // Expected sequence for config write/read
    write_reg_Expect(CS_PIN, SPI_INSTANCE, AD7606C_REG_CONFIG, 0);
    read_reg_Expect(CS_PIN, SPI_INSTANCE, AD7606C_REG_CONFIG, 1, rx_id_mismatch);
    read_reg_IgnoreArg_rx();
    read_reg_SetBuffer_rx(rx_id_mismatch, 20);

    // Expected sequence for ID read
    read_reg_Expect(CS_PIN, SPI_INSTANCE, AD7606C_REG_ID, 1, rx_id_mismatch);
    read_reg_IgnoreArg_rx();
    read_reg_SetBuffer_rx(rx_id_mismatch, 20);

    // Call the function and expect assertion failure
    TEST_ASSERT_FAIL_ASSERT(ad7606c_init(CS_PIN, SPI_INSTANCE));
}

read_reg_IgnoreArg_rx()告诉CMock忽略传入的实际参数,read_reg_SetBuffer_rx()指定要复制到被测函数参数中的数组值。

3. 验证测试环境预定义宏

检查Ceedling的project.yml,确保TEST宏已被正确定义:

:defines:
  :common:
    - TEST
    # 若需要测试INTERFACE_CHECK分支,可添加:
    # - INTERFACE_CHECK

4. 检查ID宏定义

确认被测代码中的ID宏是否为0x32,避免因宏定义不一致导致的断言失败。


内容的提问来源于stack exchange,提问作者Pranoti Joshi - Chepurwar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 17:44:55