我应该测试结果还是行为?

Should I be testing results or behaviors?

我正在尝试减少我的代码的整体性以使其成为 smaller/easier 可消化的单元,但我不确定测试的最佳实践是什么。这是一个例子:

def a(some_input):
...

def b(other_input):
    # Bunch of logic, possible other function calls
    if some_condition:
        a(...)

测试 a 对我来说似乎很简单,但是当涉及到 b 时,我是否应该测试当 b 被调用时输入导致它调用 [=11] =] 调用 a(在 python 中类似于 Mock.assert_called_with,或者我应该只是测试输出是否正确?

我对此的看法是重新使用 a 并破坏 a;我认为这是一堆误报测试失败,因为周围的 logic/behavior 是正确的,应该修复简单的 a

测试记录的输出和副作用。

例如,如果 A 只是做了一个 sub-calculation,它对 B 的输出有贡献,那么 B 的单元测试应该忽略它。 A 是 internal implementation detail and can change at any time, B might even stop calling A; if the implementation changes the test breaks. Only the documented return value of B should be testedassert_eq(b(10), 5) 或其他。

假设 A 是一个发送电子邮件的东西。这是应该测试的调用 B 的记录副作用。您可以模拟对 A 的调用并测试 B 是否传递了正确的值,而不是设置一个虚假的邮件服务器等等。 A 将单独进行单元测试。如果 A 足够复杂,您可以 split A out into a separate object 发送电子邮件并让 B 使用 A 的实例。

在well-factored代码中,每个子系统都由自己的对象管理。假设 B 正在汇总销售价格,而 A 正在进行复杂的税收计算。 A 应该是它自己的对象,它只是计算税收,单元测试 A。当单元测试 B 时,B 并不真正关心 A return 是什么,只要包含税收即可。 B 的单元测试可以将 A 模拟为 return 固定值,并测试 A 的税值是否包含在 B 的结果中。通过对 A 和 B 进行彻底的单元测试,您可以进行简单的集成测试,调用 B和真正的A.