无需断言的单元测试

37

有时候我会遇到一些没有任何断言的单元测试。今天早上我遇到的一个特例是在满足某个条件时测试是否写入了一个日志文件。假设如果没有抛出错误,测试就通过了。

我个人对此并无意见,但写一个没有任何关联断言的单元测试似乎有点“代码异味”。

想知道大家对此有什么看法?

16个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
28

这只是一个非常基本的测试,应该将其作为文档记录下来。它只验证运行时不会出错。这类测试最糟糕的地方在于它们给人一种虚假的安全感。你的代码覆盖率会提高,但这是虚幻的。味道很糟。


22

这将是官方的方法:

// Act
Exception ex = Record.Exception(() => someCode());

// Assert
Assert.Null(ex);

1
Junit5:Assertions.assertDoesNotThrow(() -> someCode()); - caduceus
xUnit.net还有Assert.DoesNotThrow(),但它的缺点是将Act和Assert结合在一行中。对于那些希望更严格遵守AAA的人来说,首选的方法是使用Record.Exception - Brad Wilson

19
如果没有断言,那就不是一个测试。 不要懒惰——花点时间弄清楚如何加入断言,这样做非常值得,因为你可以知道它是否按照你的期望运行。

哈...我倾向于这样的感觉,但我想知道在没有断言的情况下使用测试的有效原因是否存在 :) - lomaxx
对于“如果没有断言,那就不是一个测试”(至少在使用pytest时),可以参考Nick Chammas在https://dev59.com/P2Ij5IYBdhLWcg3wb0nX#20275035上的评论来提供反面观点。 - Daniel

10

这些被称为烟雾测试,很常见。它们是基本的健全性检查。但是它们不应该是你拥有的唯一测试类型。你仍然需要在另一个测试中进行某种形式的验证。


2
这些不是必要的冒烟测试:http://softwaretestingfundamentals.com/smoke-testing/ - camposer
2
这是一种烟雾测试,如果它在不抛出异常的情况下运行,那么它就通过了。 - Mark Cidade

9

这样的测试不太可靠。至少应该检查文件是否被写入,或者修改时间是否已更新。

我见过很多这样编写的测试,最终没有测试任何东西,即代码并没有起作用,但也没有崩溃。

如果你有一些明确的要求,需要测试的代码不能抛出异常,并且你想明确指出这一点(测试作为需求文档),那么我会这样做:

try
{
  unitUnderTest.DoWork()
}
catch
{
  Assert.Fail("code should never throw exceptions but failed with ...")
}

...但对我来说,这仍然有点不对劲,可能是因为它试图证明一个否定的命题。


我必须同意。我个人认为,您想要以某种方式验证写入是否发生,而不一定是写入是否正确。 - lomaxx
喜欢这个简单的解决方案。 - Adam Weitzman

4

从某种意义上说,您正在进行一种隐含的断言 - 即代码不会抛出异常。当然,实际上获取文件并找到适当的行会更有价值,但我想总比什么都没有好。


4

这是一个很好的实用解决方案,特别是如果没有测试的话。

问题在于,如果所有调用的函数都是无操作的,则测试将通过。但有时验证副作用是否符合预期是不可行的。在理想情况下,会有足够的时间为每个测试编写检查...但我不住在那里。

我使用此模式的另一个地方是将一些性能测试嵌入到单元测试中,因为这是一个简单的方法来确保每次构建时都运行它们。测试不做任何断言,但会测量测试所需的时间并记录下来。


1
我不同意 - 这不是务实,而是懒惰 ;) - ryw

3
测试的名称应该记录这一点。
void TestLogDoesNotThrowException(void) {
    log("blah blah");
}

这个测试如何验证日志是否在没有断言的情况下被写入?


2

一般来说,我认为这种情况发生在集成测试中,只要某些事情成功完成就足够了。在这种情况下,我可以接受。

如果我在单元测试中反复看到这种情况,我会好奇这些测试的实际用处。

编辑:在OP提供的例子中,有一些可测试的结果(日志文件结果),因此假设没有抛出错误就表示它有效是懒惰的。


1

我之前看过类似的情况,我认为这只是为了提高代码覆盖率而已。它可能并没有真正测试代码行为。无论如何,我同意在测试中记录其(意图),以增加清晰度。


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