是否有用于数值软件开发的测试框架

计算科学 测试
2021-11-25 06:25:27

我发现我的许多计算科学编程都有标准测试框架未涵盖的测试要求:

  1. 计算时间测试

    • 确保算法不会变慢。我可以做类似 的事情,assureSmallerEqual(RuntimeWrapper(algorithm),53)但我希望在我研究算法时不断减少 53 秒的阈值,即类似assureSmallerEqual(RuntimeWrapper(algorithm),'previousbest+noisetolerance')
  2. 性能测试

    • 确保先前找到解析解的良好近似的算法仍然可以找到至少相同或更好的解。同样,这可以通过标准集成测试来模拟,但我希望容差随着算法变得越来越好而不断缩小。考虑替换assureAlmostEqual(foo(),1,places=3)assureAlmostEqual(foo(),1,places='previousbest')
  3. 物理要求测试

    • 确保算法不会突然需要更多内存/硬盘空间。与1非常相似。
  4. 抽象需求测试

    • 为了确保在二次近似上表现良好的算法不会突然需要三次近似,或者在时间步长 0.1 上表现良好的算法不会突然需要 0.01 来保持稳定性。同样,这些可以通过标准集成测试来模拟,但目标是记住实现某个目标的最小需求参数是什么,因此这需要大量手动更新。例如,如果foo(10)之前没有抛出异常,我希望框架确保foo(10)仍然有效,并且如果现在有效,也可以尝试foo(9)(在这种情况下,所有未来的测试都将确保foo(9)仍然有效)。

有人可能会争辩说,我所要求的并不是在单元/集成测试的意义上描述测试,因为例如,增加运行时间可能是可以接受的,以换取其他改进。
然而,在实践中,我知道如果我有上面的测试功能,我会节省很多调试时间,因为在 95% 的情况下,需求和性能会因为我引入的错误而出错。事实上,我知道一个事实,如果严格应用上述测试,我可以轻松避免使用外部数值软件库发现的许多错误(在检查我自己的代码上浪费了很多时间)。

附言

类似名称的问题https://stackoverflow.com/questions/34982863/framework-for-regression-testing-of-numerical-code不是重复的,因为它描述了使用标准回归测试框架更容易实现的功能。

单元测试和测试驱动开发的问题策略要求提供策略,而不是帮助实现它们的框架(在我看来,它要求/在答案中提供的策略与我在这里描述的不同)。

1个回答

1.这种类型的测试在我看来定义不明确,因为它的测试条件与您在开发中进行测试的特定机器相关联。测试的要点之一是,在我的笔记本电脑上运行测试可以告诉我代码或我设置的环境是否有问题。53 秒是特定于您的开发机器的,如果测试机器承受其他工作负载或用户的负载,运行时间也会增加。我不希望测试框架解决这个问题:“函数在 53 秒内运行输入”并不是一个很好的正确性规范。

2.从软件测试的角度来看,我认为这是模棱两可和不可取的,原因相同1,你失去了软件测试通过或失败的理由。

3.这很常见,让我描述一种解决方案。这不是一个测试框架的工作,但您可以使用一个单独的工具,如 Unix SE 问题限制单个 Linux 进程的内存使用中所述首先要尝试的一个标准工具是ulimitin 命令bash,它可以让您运行一个进程并确保它在尝试分配太多内存时崩溃。因此,如果您runtests以内存限制运行脚本,它将崩溃,并且测试框架应该能够将其作为常规测试失败来处理。

4.大多数测试框架根本不会这样考虑单元测试运行测试套件(例如,在向 master 提交代码之前或在部署之前),结果是表示它是否起作用的是或否。测试框架不认为它是他们工作的一部分,例如,跟踪功能进度,而这通常不是测试的内容。您在这里要做的是编写两个测试expect_succeeds(foo(10)); expect_fails(foo(9))每次,两个测试都运行,成功和预期的失败都通过了。当您实施foo(9)并成功时,期望失败测试现在失败,因此您将重写expect_succeeds(foo(9)),这是所有框架的绝对标准功能。但是您必须明确说明您期望的行为,否则它会与软件测试的基本思想背道而驰。

所有这一切都有另一种方法。您正试图让测试框架在跟踪代码的迭代进度方面做额外的工作,但是测试框架在代码快照上工作并且应该工作,给出通过或失败的答案。采用算法可能更容易A, 创建一个测试套件A照原样,然后制作完整的副本AB, 进行测试performs_better(foo_A(), foo_B()), 继续努力B. 现在 (a) 测试框架将可以轻松进行比较AB,并且(b)不再有任何将代码与过去进行比较的感觉,所有代码和测试现在都是不可变且明确的。这在精神上类似于处理系统重写的方式。