单元测试数学代码

11

我正在编写一个小型实用程序,用于计算复杂的数学公式(使用commons-math库进行积分和根查找)。 我尝试以与普通业务应用程序相同的方式编写它,但是我发现我的类数量迅速增加。 为了完成第一步计算(具有2个积分的1行公式),我已经为每个计算的微小部分编写了3个类,以便我可以使用依赖注入并正确地模拟所有对commons-math的调用。 不过,这种情况有点失控了,最终我将使用20个类来解决本来可以在一个类的两个屏幕上完成的问题(没有单元测试)。 您的首选方法是什么? 对于这一个,我非常想依赖接受anceptance和更高层次的测试。


4
你谈到了对 Commons-math 进行嘲弄(mocking)的事情,我不建议这样做。Commons-math 是一段稳定可靠的代码,你可以在测试中使用它,而无需对它进行嘲弄操作。这样做能简化事情吗? - DJClayworth
如果你需要模拟20个类,也许这些类之间耦合度太高了?(高内聚性) - Stefan Hendriks
2个回答

11
不要让测试造成完全无法使用和难以理解的代码。同时,也不要过度用面向对象的方法去设计功能。
你正在测试一个函数,即一个状态无关的实体,它对于相同的参数产生相同的结果。我认为你应该这样来测试它:给它所有可能等价类的参数,并对结果进行断言。

1
+1:我同意。但是,无论你做什么,都不要在隔离的情况下省略单元测试这个函数。如果你这样做了,在尝试测试包含它的程序集时,你一定会后悔的。我从痛苦的经验中写出这句话。 - High Performance Mark

6
根据我的经验,应将单元测试用作检查代码健全性和可能的回归检查。当然,单元测试应该尽可能彻底,但有时使其完全测试代码的全部功能非常繁琐。
单元测试不是正式证明。它们不能也不会预测代码未来出现的错误和问题。测试代码的常见用例。如果需要大量可靠性,则需要创建大量的回归测试库。幸运的是,对于常见问题,有一些在线数据库可以提供这种类型的服务。例如TPLP,它是一个定理证明器问题(和解决方案)的数据库。
有时候我使用的一种技术是...通常在数学代码中,有“易但慢”的方法和“快但难以编程”的方法。在编写代码时,您希望使用快速但难以编写的方法(因此您期望有错误)。所以...将快速方式设置为系统测试(SUT)。当您进行单元测试时,请创建1000个随机问题,并使用“易但慢”的方法解决它们。然后,运行SUT并确保答案类似。
假设创建随机问题是一个容易解决的问题,有时是容易的,有时则不是。如果您不告诉我们数学代码本身,很难说。现在...这是否包含所有情况?不是。但它将涵盖“常见”情况。如果在实践中出现角落情况,请将其包装在单元测试中,并在下一个版本的代码中修复它。

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