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

时间:2012-05-29 09:13:53

标签: unit-testing audio language-agnostic tdd signal-processing

我使用音频操作,通常使用Matlab进行原型设计,使用C ++进行实现。最近,我一直在阅读TDD。我查看了几个基本的例子,对这个范例非常热衷。

目前,我使用的是全球“测试辅助”方法。为此,我用C ++编写信号处理块,然后创建一个可以与我的类接口的简单Matlab mex文件。我随后添加了功能,检查结果是否与我去的等效Matlab脚本相匹配。这项工作正常,但随着系统的发展,测试很快就会过时。更确切地说,我正在测试整个系统,而不仅仅是单位。

使用已建立的TDD框架会很好,我可以拥有一个测试套件,但是我没有看到如何验证处理块的功能,而不需要像测试中的代码一样复杂的测试。如何在C ++测试中生成参考信号以验证处理块而不将测试作为自我实现预言的一种形式?

如果有人在这方面有经验,或者可以提出一些我可以阅读的方法,那就太棒了。

4 个答案:

答案 0 :(得分:3)

我认为将TDD方法应用于信号处理是很棒的(如果我多年前在自己进行信号处理时就已经知道它,那将会节省我几个月的时间)。我认为关键是将您的系统分解为可以独立测试的最低级别组件,例如:

  • FFT:以已知频率测试信号:DC,Fs / Nfft,Fs / 2和不同相位等。检查峰值和相位是否符合预期,检查归一化常数是否符合预期
  • 峰值挑选:测试您是否正确找到最大/最小值
  • 滤波器:以已知频率生成输入,并检查输出幅度和相位是否符合预期。

你不太可能在C ++和Matlab之间得到完全相同的结果,所以你必须在某些测试中提供错误界限。 TDD是一种很好的方法,不仅可以验证您所拥有的代码的正确性,还可以在尝试不同的实现时非常有用。例如,如果要将一个FFT实现替换为另一个,则通常会与数据的打包方式或使用的规范化常数略有不同。 TDD将使您对新库正确集成具有高度的信心。

答案 1 :(得分:2)

我为启发式检测做了类似的事情,我们有大量的捕获文件和一个框架,可以加载和注入它们进行测试。您是否有可能在文件中捕获参考信号并执行相同的操作?

至于我对TDD的2美分,这是一个很好的开发方式,但和大多数范例一样,你不必总是遵循它,有时你应该知道如何弯曲规则,以免写出太多丢弃的代码/测试。我读到了一种方法,即在开发测试之前绝对不应该编写代码,这有时可能过于严格。

另一方面,我总是喜欢说:“如果没有经过测试,那就破了”:)

答案 2 :(得分:1)

测试可以比开发中的代码复杂或更复杂。如果您更改(更新,重构,错误修复)代码而不是测试,单元测试将警告您更改了某些内容并需要进行检查(模式A的错误修复是否应该更改模式B?等)

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

答案 3 :(得分:0)

我只是在信号处理的背景下开始考虑TDD,所以我只能在之前的答案中添加一些内容。我所做的是利用一些叠加来测试基元。例如,测试IIR滤波器,我独立地验证了具有单位和缩放增益的b0,b1和b2元素,然后验证了a1和a2元素,这些元素遵循容易建模的衰变。我的测试信号是分母的斜率函数和分母的脉冲函数的组合。我知道这是一个微不足道的例子,但这个过程应该适用于大量的线性操作。测试还应该运行不稳定的区域,并表明输出会发生适当的爆炸。

一般来说,我希望脉冲响应会为我做很多工作,因为很多情况会看到它们减少到三角函数,可以独立计算。同样,如果您的操作具有系列扩展,则您的测试功能可以执行扩展到相关订单并与您的处理块进行比较。它会很慢,但应该有效。