代码之家  ›  专栏  ›  技术社区  ›  Arseni Mourzenko

在进行单元测试时,100%的代码覆盖率真的是一件好事吗[[关闭]

  •  28
  • Arseni Mourzenko  · 技术社区  · 15 年前

    我一直了解到,通过单元测试实现最大的代码覆盖率是非常重要的 好的

    现在, 真的很棒吗? 有时是不是像 完全丧失时间 使维护更加困难 ?

    例如,假设我有一个方法 DisplayBooks() 它填充数据库中的图书列表。产品要求告诉我们,如果店里有一百多本书, 只能显示100个 .

    1. 我先做一个单元测试 BooksLimit() DisplayBooks() ,然后做一个 Assert.AreEqual(100, DisplayedBooks.Count) .
    2. 如果失败了我会测试,
    3. 那我就换衣服 将结果限制设置为100,以及
    4. 最后,我将重新运行测试,看看它是否成功。

    好吧,直接走到第三步不就容易多了吗 限制()

    注意:假设代码是完全文档化的。否则,一些人可能会说,做完整的单元测试将有助于理解缺乏文档的代码,这是正确的。事实上 单元测试将非常清楚地显示要显示的书籍的最大数量,并且这个最大数量是100。进入非单元测试代码将非常困难,因为这样的限制可能会实现 for (int bookIndex = 0; bookIndex < 100; ... foreach ... if (count >= 100) break;

    8 回复  |  直到 11 年前
        1
  •  34
  •   Stephen    15 年前

    对。。。如果你不花时间写测试,你会花更少的时间写测试。您的项目可能需要 比较长的 总的来说,因为你会花很多时间调试,但也许这更容易向你的经理解释?如果是这样的话。。。找份新工作!测试对于提高您对软件的信心至关重要。

    当您拥有大量代码时,单元测试提供了最大的价值。不用单元测试,用几个类就可以很容易地调试一个简单的家庭作业。一旦你走出这个世界,你在数百万行的代码库中工作-你会需要它的。你不可能一步一步地完成你的调试器。你不可能什么都懂。你需要知道你所依赖的课程是如何工作的。你要知道如果有人说“我要改变我的行为。。。因为我需要它“,但是他们忘记了还有两百种其他的用途依赖于这种行为。单元测试有助于防止这种情况。

    关于提高维护难度: 不可能! 我不能充分利用这一点。

    如果你是唯一一个参与过你的项目的人,那么是的,你可能会这么想。但那是胡说八道!在没有单元测试的情况下,试着跟上30k线路项目的进度。尝试添加需要在没有单元测试的情况下对代码进行重大更改的功能。有 没有信心

    关于保险范围的说明:

    对我来说,这不是100%的测试覆盖率。100%覆盖率并不能找到所有的bug,考虑一个有两个bug的函数 if 声明:

    // Will return a number less than or equal to 3
    int Bar(bool cond1, bool cond2) {
      int b;
      if (cond1) {
        b++;
      } else {
        b+=2;
      }
    
      if (cond2) {
        b+=2;
      } else {
        b++;
      }
    }
    

    现在考虑编写一个测试:

    EXPECT_EQ(3, Bar(true, true));
    EXPECT_EQ(3, Bar(false, false));
    

    100%覆盖。这也是一个不符合合同的功能- Bar(false, true);

    老实说,我会跳过考试的 BooksLimit() . 它返回一个常量,因此可能不值得花时间编写它们(在编写时应该进行测试) DisplayBooks() ). 当有人决定(错误地)根据货架尺寸计算限制时,我可能会很难过,因为它不再满足我们的要求。我以前被“不值得测试”所折磨。去年我写了一些代码,我对同事说:“这个类主要是数据,不需要测试。”。它有一个方法。它有个窃听器。它投入生产。它半夜呼叫我们。我觉得自己很愚蠢。所以我写了测试。然后我仔细思考了很久,什么代码是“不值得测试的”。没有多少。

    如果我把 class A , class B class C 一起,我发现一些不工作,我想花时间调试这三个吗?不,我想知道 A B 已经满足了他们的合同(通过unittests)和我的新代码 可能坏了。所以我测试了一下。如果我不测试,我怎么知道它坏了?通过点击一些按钮并尝试新代码?这很好,但还不够。一旦您的程序扩展,就不可能重新运行所有手动测试来检查一切是否正常。这就是为什么使用unittest的人通常也会自动运行他们的测试。告诉我“通过”或“失败”,不要告诉我“输出是…”。

        2
  •  12
  •   soru    15 年前

    100%的单元测试覆盖率通常是一种代码味道,这是一种迹象,表明有人在覆盖工具的绿色条上忽略了所有的OCD,而不是做一些更有用的事情。

    大约有85%是最佳点,测试失败的频率更高,并不表明存在实际或潜在的问题,而不仅仅是注释标记之外的任何文本更改的必然结果。如果您的假设是“代码就是它是什么,如果它以任何方式不同,它将是另一种东西”,那么您就没有记录任何关于代码的有用假设。这是一个由注释感知的校验和工具解决的问题,而不是一个单元测试。

    我希望有一些工具可以让你指定目标覆盖率。如果你不小心看了一遍,用黄色/橙色/红色显示一些东西,以促使你删除一些虚假的额外测试。

        3
  •  6
  •   Lucero    15 年前

    当你看到一个孤立的问题时,你是完全正确的。但是单元测试是关于覆盖你对某段代码的所有意图。

    基本上,单元测试描述了您的意图。随着意图数量的不断增加,要测试的代码的行为总是可以对照到目前为止所做的所有意图进行检查。无论何时做出改变,你都可以证明没有任何副作用会破坏现有的意图。新发现的bug只不过是一个(隐式的)意图,代码并不持有这个意图,因此您可以将您的意图表述为新测试(一开始失败)并修复它。

    对于一次性代码,单元测试确实不值得付出努力,因为不需要进行重大更改。然而,对于任何要维护的代码块或作为其他代码的组件的代码块,保证所有新版本的意图都被保留是非常有价值的(就手动尝试检查副作用的工作量而言)。

    单元测试实际节省时间和金钱的临界点取决于代码的复杂性,但总有一个临界点,通常只需经过几次迭代就可以达到。此外,最后但并非最不重要的是,它允许您在不影响产品质量的情况下更快地发布修复和更改。

        4
  •  5
  •   dzida    15 年前

    代码覆盖率和好的软件之间没有必然的联系。您可以很容易地想象一段代码有100%(或接近)的代码覆盖率,但它仍然包含许多bug(这并不意味着考试不好!)

    你关于“完全不测试”方法的敏捷性的问题是一个很好的问题,只是从短期的角度来看(这意味着如果你计划用更长的时间来构建你的程序的话,它很可能是不好的)。根据我的经验,当你的项目越来越大,在某个阶段你需要做出重大的改变时,这种简单的测试是非常有用的。当你对自己说 “多花点时间来编写发现我刚刚介绍的bug的小测试,这是一个很好的决定!” .

    我最近非常喜欢代码覆盖,但现在它(幸运地)变成了 '问题覆盖' 接近。这意味着你的测试应该涵盖所有的问题和缺陷,而不仅仅是 '代码行' . 没有必要做一个 '代码覆盖率竞赛'

    '帮助我构建好软件、不浪费时间编写不必要代码的测试数量' 而不是“100%覆盖”或“完全没有测试”。这是非常主观的,它基于你的经验,团队,技术和许多其他因素。

    “100%代码覆盖率”的心理副作用是,你可能认为你的代码没有bug,这从来都不是真的:)

        5
  •  2
  •   fishtoprecords    15 年前

    我不相信任何工具或指标可以存在,可以告诉你“正确的”数额的覆盖面。我读研究生时,我的论文导师的工作是为“变异”代码设计测试覆盖率。他做了一套测试,然后运行一个自动程序,在测试的源代码中出错。这个想法是变异后的代码包含了在现实世界中可以发现的错误,因此一个测试套件找到了最高百分比的坏代码,它就是赢家。

    虽然他的论文被录取,他现在是一所主要工程学院的教授,但他没有发现:

    1) 最佳测试覆盖率的神奇数字

    注意,目标是找到100%的错误,而不是找到100%的覆盖率。

    @soru的85%是否正确是一个值得讨论的话题。我没有办法评估一个更好的数字是80%还是90%或者其他什么。但作为一个工作评估,85%的人认为我是对的。

        6
  •  2
  •   Shivprasad Koirala    12 年前

    对不起我的英语。

    我们的目标应该是测试一些复杂的东西,而不仅仅是所有的东西。现在这个复合体需要用一些度量数来表示,这些度量数可以是圈复杂度、代码行、聚合、耦合等,也可以是上述所有事物的顶点。如果我们发现度量值更高,我们需要确保代码的这一部分被覆盖。下面是我的文章,涵盖了什么是最好的%的代码覆盖率。

    Is 100% code coverage really needed ?

        7
  •  1
  •   Hannoun Yassir    15 年前

    第一个100%是很难得到特别是在大项目!即使您在代码块被覆盖时这样做了,也并不意味着它正在做它应该做的事情,除非您的测试正在断言每一个可能的输入和输出(这几乎是不可能的)。

    所以我不认为一个软件是好的,因为它有100%的代码覆盖率,但代码覆盖率仍然是一件好事。

    好吧,直接进入第三步,并且永远不进行BooksLimit()单元测试不是更容易吗?

        8
  •  0
  •   Chubas    15 年前

    当客户机决定将限制更改为200时,祝您好运找到与这个看似微不足道的测试相关的bug。特别是,当你的代码中有其他100个变量时,还有其他5个开发人员在处理依赖于这一小部分信息的代码。

    我的观点是:如果它对业务价值有价值(或者,如果你不喜欢这个名字,对项目非常重要的核心有价值),那么就测试它。只有在没有可能的(或廉价的)测试方法时,比如UI或用户交互,或者当您确定不编写测试的影响最小时,才放弃。对于需求模糊或快速变化的项目(我痛苦地发现),这一点更为正确。

    对于您介绍的另一个示例,建议使用测试边界值。因此,您可以将测试限制为四个值:0、介于0和BooksLimit之间的神奇数字、BooksLimit和更高的数字。