Unit testing 如何判断单元测试是正确的?

Unit testing 如何判断单元测试是正确的?,unit-testing,tdd,Unit Testing,Tdd,在我的职业生涯中,我只在不同的时候做过一些小的单元测试。每当我再次开始钻研它时,它总是困扰着我如何证明我的测试是正确的。我如何判断我的单元测试中没有bug?通常我会运行应用程序,证明它是有效的,然后使用单元测试作为一种回归测试。您对此问题的建议方法和/或采取的方法是什么 编辑:我还认识到,您可以编写易于理解的小型、细粒度的单元测试。然而,如果您假设小而细粒度的代码是完美的和防弹的,那么您可以只编写小而细粒度的程序,而不需要单元测试 Edit2:对于“单元测试是为了确保您的更改不会破坏任何东西”和

在我的职业生涯中,我只在不同的时候做过一些小的单元测试。每当我再次开始钻研它时,它总是困扰着我如何证明我的测试是正确的。我如何判断我的单元测试中没有bug?通常我会运行应用程序,证明它是有效的,然后使用单元测试作为一种回归测试。您对此问题的建议方法和/或采取的方法是什么

编辑:我还认识到,您可以编写易于理解的小型、细粒度的单元测试。然而,如果您假设小而细粒度的代码是完美的和防弹的,那么您可以只编写小而细粒度的程序,而不需要单元测试


Edit2:对于“单元测试是为了确保您的更改不会破坏任何东西”和“只有当测试与代码有完全相同的缺陷时才会发生这种情况”的论点,如果测试超出范围怎么办?有可能通过一个坏的测试同时通过好的和坏的代码。我的主要问题是单元测试有什么好处,因为如果你的测试有缺陷,你就不能真正提高你对代码的信心,不能真正证明你的重构工作正常,也不能真正证明你符合规范?

我想先写测试(在写代码之前)这是一个很好的方法来确保你的测试是有效的


或者您可以为单元测试编写测试…:P

你不说。一般来说,测试会比他们正在测试的代码简单,所以我们的想法很简单,他们比真正的代码更不可能有bug。

如上所述,最好的方法是在实际代码之前编写测试。如果适用,也可以找到测试代码的实际示例(数学公式或类似公式),并将单元测试和预期输出与之进行比较。

Dijkstra有句名言:

“测试表明存在,而不是存在 没有bug“

那么,如何为函数add(int,int)编写单元测试呢


瞧,这是一个困难的问题。

如果这是一个问题,那么您的代码必须有缺陷,并且碰巧会导致您的测试通过。这种情况最近发生在我身上,我正在检查给定的条件(a)是否导致方法失败。测试通过(即方法失败),但它通过了,因为另一个条件(b)导致了失败。仔细编写测试,并确保单元测试测试一件事


不过,一般来说,无法编写测试来证明代码没有bug。它们朝着正确的方向迈出了一步。

这是每个使用单元测试的人都会遇到的问题。如果我必须给你一个简短的回答,我会告诉你永远相信你的单元测试。但我想说的是,这应该与你以前的经验相吻合:

  • 您是否有任何手动测试报告的缺陷,而单元测试没有捕获(尽管它有责任),因为您的测试中存在错误
  • 你过去有过假阴性吗
  • 你的单元测试足够简单吗
  • 您是在编写新代码之前编写它们,还是至少并行编写

单元测试应该表达您正在测试的任何东西的“契约”。这或多或少是将单元的规范转化为代码。因此,考虑到规范,单元测试是否“正确”应该或多或少是显而易见的

但是我不会太担心单元测试的“正确性”。它们是软件的一部分,因此,它们也可能是不正确的。从我的观点来看,单元测试的目的是确保软件的“契约”不会因意外而被破坏。这就是使单元测试如此有价值的原因:你可以在软件中挖掘,重构某些部分,更改其他部分的算法,你的单元测试会告诉你你是否破坏了任何东西。即使是不正确的单元测试也会告诉您这一点

如果单元测试中有一个bug,你会发现的——因为单元测试失败了,而测试的代码被证明是正确的。那么,修复单元测试。没什么大不了的

  • 单元测试代码的复杂性(或应该)比实际代码低(通常低几个数量级)
  • 在单元测试中编写与实际代码中的错误完全匹配的错误的可能性远远小于在实际代码中编写错误(如果在单元测试中编写与实际代码中的错误不匹配的错误,则应该失败)。当然,如果您在实际代码中做出了不正确的假设,您很可能会再次做出相同的假设——尽管单元测试的思维方式仍然应该减少这种情况
  • 正如前面提到的,当您编写单元测试时,您有(或应该有)不同的思维定势。当编写真正的代码时,你会想“我该如何解决这个问题”。在编写单元测试时,您会想,“我如何测试所有可能出现故障的方法?”
  • 正如其他人已经说过的,这与你能否证明单元测试是正确的和完整的无关(尽管测试代码几乎可以肯定这要容易得多),因为它将bug数量减少到一个非常低的数字,并将它推得越来越低


    当然,在一定程度上,您对单元测试有足够的信心来依赖它们——例如在进行重构时。达到这一点通常只是一个经验和直觉的例子(尽管有代码覆盖工具可以提供帮助)。

    您无法证明测试是正确的,如果您试图证明,您就错了

    单元测试是第一屏——冒烟测试——就像所有自动化测试一样。他们主要是在那里告诉你,如果你以后做的改变会破坏你的东西。即使在100%的覆盖范围内,它们也不是为了证明质量


    不过,这一指标确实让管理层感觉更好,这本身有时也很有用

    有两种方法可以帮助确保单元测试的正确性:

    • TDD:先写测试,然后写c