面向信号处理库的测试驱动开发

12

我从事音频处理工作,通常使用Matlab进行原型设计,使用C++进行实现。最近,我一直在阅读有关TDD的资料。我查看了一些基本示例,并对这种编程范式非常热衷。

目前,我使用的是我认为是全局“测试辅助”方法。为此,我用C++编写信号处理模块,然后制作一个简单的Matlab mex文件,可以与我的类进行接口交互。随后,我添加功能,检查结果是否与等效的Matlab脚本匹配。这种方法还算可以,但随着系统发展,测试很快就变得过时了。此外,我正在测试整个系统,而不只是单元。

使用一个已经建立起来的TDD框架会很好,因为我可以拥有一个测试套件,但我不知道如何在没有与被测试代码同样复杂的测试的情况下,验证处理块的功能。如果测试成为自我实现预言的形式,那么如何生成C++测试中的参考信号来验证处理块呢?

如果有人在这个领域有经验,或者可以建议我一些方法论,那就太好了。


2
+1 测试信号处理并不容易;但需要注意的是:测试C++结果与Matlab结果相同只能证明这一点,但不能证明结果是正确的:因为Matlab和C++都可能给出相同但不正确的结果。 - stijn
4个回答

3
我认为将TDD方法应用于信号处理非常棒(如果我在做信号处理时早些知道这一点,那么可以节省我数月的时间)。关键是要将系统分解成最低级别的组件,可以进行独立测试,例如:
  • FFT:测试已知频率的信号:DC、Fs/Nfft、Fs/2和不同相位等。检查峰值和相位是否符合预期,检查归一化常数是否符合预期
  • 峰值拾取:测试是否正确找到极大值/极小值
  • 滤波器:生成已知频率的输入并检查输出幅度和相位是否符合预期。
您很可能无法完全在C++和Matlab之间得到相同的结果,因此您必须对某些测试提供误差范围。TDD不仅是验证您代码正确性的好方法,而且在尝试不同实现时非常有用。例如,如果您想用另一个FFT实现替换一个,则通常数据打包方式或使用的规范化常数有所不同。TDD将使您对新库正确集成有很高的信心。

2
我在启发式检测方面做了类似的工作,我们有大量的捕获文件和一个框架来加载和注入它们进行测试。你有可能将参考信号捕获到一个文件中并执行相同的操作吗?
至于我的两分钱关于TDD,这是一种很好的开发方式,但像大多数范例一样,你不总是必须完全遵循它,有时候你应该知道如何稍微打破规则,以免写太多的一次性代码/测试。我读过一种方法,它说在开发测试之前绝不能编写任何代码,这有时可能太严格。
另一方面,我总是喜欢说:“如果没有经过测试,那就是有问题的” :)

1

测试可以比正在开发的代码更复杂,甚至更加复杂也没关系。如果你修改(更新、重构、修复错误)了代码而没有修改测试,单元测试将会警告你有些东西已经改变并需要进行审查(例如:模式A的错误修复是否应该改变模式B?等等)。

此外,你可以维护各个计算组件的API,而不仅仅是整个端到端系统的API。


0

我刚开始考虑在信号处理的TDD方面,所以我只能对之前的答案做出一点补充。我利用了一些叠加原理来测试基元。例如,测试IIR滤波器时,我独立验证了带有单位和缩放增益的b0、b1和b2元素,然后验证了a1和a2元素,这些元素很容易模拟衰减。我的测试信号是分子的斜坡函数和分母的脉冲函数的组合。我知道这是一个微不足道的例子,但这个过程应该适用于许多线性操作。测试还应该练习不稳定的区域,并显示输出适当地爆炸。

总的来说,我预计脉冲响应将为我做很多工作,因为许多情况下它们会简化为三角函数,可以独立计算。同样,如果您的操作具有级数展开,您的测试函数可以将展开执行到相关顺序,并与您的处理块进行比较。这会很慢,但应该有效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接