Pytest单元测试一例:u16采样值格式转换的错误

1.一个失败的测试用例

python 复制代码
def test_fft_in_selfmade_signal():

    freq_shutdown = 5000

    scale_max_in_g = 50

    (x, sig_h, sig_v, fullpath_of_file) = gp_xjtu_data.get_demo_data_in_u16()

    acc_in_std_h = [(int(xx)-int(32768))*scale_max_in_g*9.8/32768 for xx in sig_h]

    assert min(acc_in_std_h)/scale_max_in_g/9.8 == pytest.approx((int(min(sig_h))-int(32768))*scale_max_in_g*9.8/32768, 0.1), f"u16->fft(input_in_std_acc) error. min_ar should{min(acc_in_std_h)*50*9.8}, ref_value={(int(min(sig_h))-int(32768))*50*9.8/32768}" #fomula 1

这是一个pytest usecase.

输出:

AssertionError: u16->fft(input_in_std_acc) error. min_ar should-6711.779785156252, ref_value=-13.697509765625002

问题出在哪里?数据源没问题,已经校准过。

1.1 相关补充信息

  • get_demo_data_in_u16得到一组[0,65536]的采样信号。
  • 零点在32768,下负上正,然后上下实际物理量的机制,ppk对应[-50,+50]。
    • 50就是那个scale_max_in_g
  • acc_in_std_h 是打算将这个u16格式的数字采样序列转换为的国际单位制
  • 然后我需要比对转换前后的一致性。

2.纠错

2.1 acc_in_std_h转换的对吗?

python 复制代码
acc_in_std_h = [(int(xx)-int(32768))*scale_max_in_g*9.8/32768 for xx in sig_h]

感觉这一步似乎没有问题。

  • u16数据不能直接和差运算,因为会溢出。所以先转换为有符号int,再加减。
  • 后续的缩放也没有问题。

2.2 assert有几个错误?

1. assert比较需要先对准同一个单位。我们看看对准的是什么:

lhs...物理意义是满量程的归一化值[-1~+1]
python 复制代码
min(acc_in_std_h)/scale_max_in_g/9.8

#acc是国际单位制的m/s^2。

#除以9.8是换算为g

#除以scale_max_in_g,是换算成了满量程的归一化值。
rhs.物理意义是acc国际单位制,不妥。决定向lhs的归一化形式靠拢
python 复制代码
pytest.approx((int(min(sig_h))-int(32768))*scale_max_in_g*9.8/32768, 0.1)
# sig_h是原始采样值
# 首先变成有符号更大尺度的数字然后减去零点
# 然后这是变成了acc值。
# 所以此处有误。
# 因为acc值不足以很好地表征信噪比,所以,此处应该修改为:
pytest.approx((int(min(sig_h))-int(32768))*1/32768, 0.1)

#上面的算是rhs也修改为[-1~+1]的满量程归一化形式。对吧?

用打印值验证一下:

python 复制代码
#第一个打印值的物理意义是:acc*500,它没有实际含义。
{min(acc_in_std_h)*50*9.8}, 
#第二个打印值的物理意义是:acc,
ref_value={(int(min(sig_h))-int(32768))*50*9.8/32768}
#所以,第一个打印值应该是第二个打印值的近500倍,确切地说是490倍。

#验算一下:
-6711.779785156252/490 == -13.697509765625002

3. 规避策略

凡是涉及到进制转换的代码。一律必须给出单位注释,打印值也要给出单位,比较需要给出等式的物理意义。修正后的代码:

python 复制代码
def test_fft_in_selfmade_signal():
    freq_shutdown = 5000
    scale_max_in_g = 50
    (x, sig_h, sig_v, fullpath_of_file) = gp_xjtu_data.get_demo_data_in_u16()
    # acc_in_std_h unit:(ms^2 == 9.8*g)
    acc_in_std_h = [(int(xx)-int(32768))*scale_max_in_g*9.8/32768 for xx in sig_h]

    #lhs unit:[-1 ~ +1]
    lhs = min(acc_in_std_h)/scale_max_in_g/9.8
    #rhs unit:[-1 ~ +1]
    rhs = (int(min(sig_h))-int(32768))*1.0/32768
    eps = 1e-5
    assert lhs == pytest.approx(rhs, eps), f"u16->fft (input_in_std_acc) error. 归一化值比对结果:lhs {lhs}, rhs={rhs}, 精度={eps}"

3.1执行结果反馈

4.常见的转换错误 - 示例

4.1 零点错误

判定标准:一旦出现坐标值出现恒定的负量程,一定是零点偏了。

|----------------------------------------------------------------------------|----------------------------------------------------------------------------|
| 正确 | 错误 |
| | |

相关推荐
l1t1 天前
利用DeepSeek辅助修改luadbi-duckdb读取DuckDB decimal数据类型
c语言·数据库·单元测试·lua·duckdb
lang201509281 天前
Spring Boot日志配置完全指南
java·spring boot·单元测试
我的xiaodoujiao2 天前
使用 Python 语言 从 0 到 1 搭建完整 Web UI自动化测试学习系列 22--数据驱动--参数化处理 Json 文件
python·学习·测试工具·pytest
安冬的码畜日常2 天前
【JUnit实战3_23】 第十四章:JUnit 5 扩展模型(Extension API)实战(上)
测试工具·junit·单元测试·jdbc·h2·extension模型·junit5扩展
胜天半月子3 天前
Python自动化测试 | 快速认识并了解pytest的基本使用
服务器·python·pytest
慧都小项3 天前
Parasoft C/C++test如何在ARM DS-5环境中进行测试(下)
单元测试·parasoft·arm ds-5
JosieBook3 天前
【SpringBoot】30 核心功能 - 单元测试 - JUnit5 单元测试简介与常用注解实战详解
spring boot·后端·单元测试
l1t3 天前
对luasql-duckdb PR的测试
c语言·数据库·单元测试·lua·duckdb
卓码软件测评4 天前
单元测试、集成测试和系统测试的联系和区别是什么?
功能测试·单元测试·测试用例·集成测试·可用性测试
安冬的码畜日常4 天前
【JUnit实战3_20】第十一章:用 Gradle 运行 JUnit 测试实战
测试工具·junit·单元测试·gradle·软件构建·groovy·junit5