【发布时间】:2020-02-26 09:43:49
【问题描述】:
我有函数 f 和 g,它们已经有一组单元测试,确保它们的行为对于某些已知的输入输出对(加上异常处理等)是正确的。
现在我正在创建函数h(),如下:
def h(x):
return f(x) + g(2*x)
对这个函数进行单元测试的好方法是什么?如果h() 更加复杂,这种情况会改变吗?
到目前为止我的想法:
我看到了测试h() 的两种可能性。
1。测试h() 是否在做正确的“管道”
模拟f(),以便在使用输入x_0 调用时返回y_0;模拟g(),以便在使用输入2*x_0 调用时返回z_0。然后检查调用h(x_0) 是否返回y_0+z_0。
优势:
- 实施测试非常简单。
- 可以快速找到错误连接
f和g的输出,或使用错误参数调用它们的错误(例如,在h()中调用g(x)而不是g(2*x))。李>
缺点:
- 这是测试如何,而不是什么
h()应该做什么。如果以后我想重构h(),那么我可能需要重写这些类型的测试。 - 如果测试指定的管道没有为
h()产生预期的高级行为,那么这些测试将不会捕获此错误。例如,可能正确的管道应该是f(-x) + g(2*x),而我在函数定义和测试定义中都弄错了。
2。测试 什么 h() 应该做什么
假设h() 的目的是计算给定参数以下的素数之和。在这种情况下,h() 的自然测试套件将涉及使用已知的输入输出对对其进行测试。确保h(1)=2、h(2)=5、h(5)=28 等不关心如何 h() 计算这些数字的东西。
优势:
- 这种类型的测试检查
h()确实遵循其预期的高级行为。任何改变这一点的管道错误都将被捕获。 - 重构
h()可能不需要更改测试套件,甚至会更容易,因为测试帮助我们保证函数的行为不会改变。
缺点:
- 在这个简单的示例中,很容易生成这样的对,因为
h()执行的映射不是很复杂(只需将n的第一个素数相加即可)。然而,对于一个非常复杂的h(),我生成此类对的唯一选择可能是我想出一个输入x并手动计算正确的输出。如果h非常复杂,这似乎不合理。 - 由于提出已知的输入-输出对需要我计算
f()和g()在给定特定输入的情况下会产生什么,因此可能会有一些重复的工作,因为我在创建时已经花费了一些时间这些功能的单元测试。
相关问题:Unit testing composite functions.
这个问题乍一看和我的很相似。然而,投票最多的两个答案提出了完全不同的解决问题的方法(我上面提到的两种方法)。我的问题是试图澄清每种方法的优缺点(也许还可以学习其他方法),并可能确定哪种方法总体上最好。如果没有一种方法在所有情况下都是最好的,我想了解在哪些情况下应该使用它们中的每一种。
【问题讨论】:
标签: unit-testing testing