我的代码包含许多小函数f_put_things_together()
。
这些都可以单独进行单元测试。
但在现实世界中,你经常会有一个复杂的函数f_put_things_together
需要调用较小的函数。
单元测试func f_put_things_together() {
a = f_small_1()
if a {
f_small_2()
} else {
f_small_3()
}
f_small_4()
...
f_small_10()
}
的好方法是什么?
f_put_things_together
我开始编写测试但是我觉得我已经两次这样做,因为我已经测试了较小的函数。
我可以a1.f_small_1()
将对象a1,a2,...,a10作为参数并调用a2.f_small_2()
,KVO
,...以便我可以单独模拟这些对象但这对我来说不合适:如果我不必编写单元测试,那么所有这些函数在逻辑上都属于同一个类,并且我不想为了测试而有不清楚的代码。
这在某种程度上与语言无关,不知何故,因为像Python这样的语言可以让你替换对象的方法。因此,如果您的答案与语言无关,那就是最好的。我目前正在使用Go。
答案 0 :(得分:1)
您在示例中显示的一般情况表明需要测试简单函数和这些函数结果的聚合。在测试聚合函数时,您真的想伪造聚合函数所依赖的较小函数的结果。所以,你走在正确的轨道上。
但是,如果您在为代码编写单元测试时遇到问题,那么您可能遇到以下类别的问题之一:
如果您的测试很难写,那么他们会告诉您一些事情!根据经验,您将能够快速了解您的实施中的测试结果。指示。
不幸的是,你的例子有点小而且抽象。更准确地说,我不知道f_small_1
... f_small_10
做了什么。因此,有了更多的细节,我可能会做一些更精确的建议来做一些小的重构,这可能会给你的测试带来很大的回报。
f_put_things_together
看起来对我来说有点大。这可能违反了单一责任原则(SOLID中的'S')。我至少看到10个函数调用以及一些分支逻辑。
您需要通过函数为每个分支路径编写单独的测试。您在特定函数中的分支越少,您需要编写的测试就越少。有关更多信息,请查看Cyclomatic Complexity。在这种情况下,似乎该方法具有较低的CC,因此这可能不是问题。
对较小功能的十次调用确实让我有些疑惑。为简单起见,您似乎忽略了捕获这些函数调用的返回值以及聚合结果的逻辑。在这种情况下,是的,你确实想要伪造较小函数的结果,然后编写一些测试来检查你用来聚合所有内容的算法。
或者,也许这些功能都是无效的,你需要验证一切都发生了,也许它是以正确的顺序发生的。在这种情况下,您正在考虑编写更多基于交互的测试。您仍然希望将这些较小的函数调用放在您伪造的接口/类/对象后面。在这种情况下,假冒应捕获调用和调用顺序,以便您的测试可以使断言真正重要。如果某些较小的函数彼此相关,则可以将它们组合在一个单独的方法中。然后,您对f_put_things_together
的测试将具有较少的需要伪造的依赖项。你将有一个新的类也需要测试,但测试两个较小的方法比测试一个有太多责任的大的方法要容易得多。
这实际上是一个非常好的问题,除了它有点模糊。如果您可以提供更详细的示例,也许我可以提供更详细的建议。最重要的是:如果您的测试难以编写,那么您在编写测试时需要一些帮助/指导,或者关于您的实现设计的某些内容已关闭,您的测试试图告诉您它是什么。