代码之家  ›  专栏  ›  技术社区  ›  Sorskoot

单元测试如何提高生产力?

  •  6
  • Sorskoot  · 技术社区  · 15 年前

    我目前正在寻找提高团队生产力的方法。我在很多地方读到过单元测试可以用来提高生产力。我可以想象,现在编写单元测试在将来会有帮助,但在短期内也会有帮助吗?因为我不明白写更多的代码(更多潜在的错误)是如何帮助我们完成最后期限的。

    15 回复  |  直到 7 年前
        1
  •  14
  •   Eric    15 年前

    单元测试不是每天生成更多的代码行。

    它是为了确保每天新的代码行不会导致更多的错误。

    当你试图评估你的“生产力”时,你需要非常小心你所想的。不过,这可能有助于你在截止日期前完成工作,因为你会花更少的时间来完成工作。

    它不是针对“短期”的东西,比如“我们将使用单元测试,我们的下一个项目将在80%的时间内完成”。

        2
  •  7
  •   Pascal MARTIN    15 年前

    不是 短的 但不是 长的 术语二者之一,自动测试将允许您检测问题 (回归) 由错误的bug修复或错误的开发导致的,速度更快;这确实很好。

    这意味着,当您的应用程序处于测试阶段时,每次修正一个bug,您引入新bug的风险就会降低。
    只要应用程序仍在开发中,这也是正确的:每当开发人员提交一个新模块时,您就知道它不会破坏应用程序的其余部分。 (或者,至少它不会破坏自动化测试所涵盖的内容)

    检测到错误越早,修复的过程就越简单,成本也就越低。 :如果一个bug没有时间影响其他开发人员,那么它也会更好。
    如果开发人员认为某个“bug” (他不知道这是一只虫子) 作为一个特性并开始依赖它?当这开始被视为一个bug并被修复时会发生什么?我想,其他代码会中断:-(


    另外,开发自动化测试也意味着更多的开发人员对应用程序的代码了解更多:特别是如果一些测试是由其他开发人员开发/审查的,而不是最初编写代码的开发人员。
    不确定这是“良好的实践”,但如果这样做,意味着将有某种代码审查到位——而那些无疑是有帮助的。

    而且,随着开发人员对代码的了解越来越多,开发人员将能够修复他们最初没有开发的部分中的错误。

        3
  •  6
  •   rahul    15 年前

    Increasing productivity with unit testing

    也读 Test Driven Development

    测试驱动开发(TDD)是一种 软件开发技术 使用短开发迭代 基于预先编写的测试用例 定义所需的改进或新的 功能。每次迭代都会产生 传递该信息所需的代码 迭代的测试。最后, 程序员或团队重构代码 以适应变化。密钥TDD 概念是在 编码有助于快速反馈 变化。注意,测试驱动 开发是一种软件设计 方法,而不仅仅是 测试。

        4
  •  4
  •   John Parker    15 年前

    虽然这是一个严重的过度暗示,但越早发现一个bug,修复它的成本就越低。因此,单元测试至少会预先捕获一些错误。

    我怀疑,就生产率而言,这是一个问题,即是否更容易修复程序员头脑中新鲜的代码中的错误,而不是“n”个月前的代码中的错误,等等。然而,假设单元测试(在更大的测试制度之外)是某种形式的银弹,这有点理想主义。

        5
  •  4
  •   kyoryu    15 年前

    “test”是单元测试中的错误词。定义行为,“也许是一个更好的术语。

    单元测试和TDD可以通过多种方式提高生产力(甚至中期)。

    • 具有定义良好行为的代码更容易调试,正如所预期的行为所知。
    • 用TDD方法编写的代码往往具有更清晰的“接缝”,从而允许单独验证代码库的各个部分。这使得在问题发生时更容易缩小范围。
    • 由于强大的测试套件和定义良好的行为,重构变得非常容易。这使得设计问题能够以更低的风险得到解决,即使它们影响到许多单独的类。
    • 由于上述原因,通常在出现问题时更容易确定修复的正确位置。
    • 由于TDD编写的代码往往不太依赖于单例/静态行为或全局状态,因此存在的全局行为更少。随着全球行为的减少,副作用也会减少。

    根据我的经验,TDD编写代码的最大优势在于 定义良好的 . 首先定义代码 应该做 然后让它这样做。这与“常规”的开发实践形成了鲜明的对比,后者通常需要编写大量的代码,然后测试代码,看看它实际上做了什么。

    使用类似TDD的方法的另一个好处是,即使端到端解决方案不到位,您几乎可以立即获得工作代码。而且,添加到工作代码中以获得更多工作代码几乎总是容易的,而不是编写一组处于未知状态的代码,然后找出不正确的代码。

        6
  •  3
  •   djna    15 年前

    没有单元测试,你打算怎么测试?通过点击周围,目视检查答案?编写一次代码并运行多次是成本还是节约?

    你打算练习各种错误条件吗?如果不及早而不迟地修复bug的相对成本是多少,您以后会发现这些bug吗?

    然而,对我来说,最重要的原因是一个不那么明显的原因:如果你首先编写测试(真正的TDD),或者甚至在你进行测试的时候,你几乎是在考虑边缘案例。结果就是代码更好了。少返工。

    另一种理论是,人类非常注重目标。我们喜欢奖励,重复给我们奖励的行为(嗯,声誉,嗯…给我一个问题来回答:当我们的测试通过时,看到那些绿色的小滴答声会激励我们。你可能会得到更多的代码,但它写得更快。

        7
  •  2
  •   Stefano Borini    15 年前

    我可以想象现在编写单元测试 将来可能会有所帮助,但确实如此 短期内也有帮助吗?

    是的,因为您强制开发人员和架构师一次解决一个问题。

    因为我不明白怎么写 更多的代码(=更多的潜在错误)可以 帮助我们完成最后期限。

    附加代码的数量完全相同。n行逻辑=n行测试。但正如您所知,原始编码并不是需要花费更多时间的部分,特别是因为您可以很好地将其并行化。所以写更多的代码不是真正的问题。为了满足最后期限,你必须 顶部 质量 要发布的代码,没有测试

    1. 不知道质量是不是最高的。
    2. 无法测量何时可以释放。(当所有测试作为首要条件通过时)
        8
  •  2
  •   Michael Easter    15 年前

    这里有一些想法。对于我的答案,我将把生产力定义为行数除以错误数。如果应用得当,平均来说,我认为单元测试将产生更高的生产力。

    1. Stuart Halloway使用了双分类账会计的比喻:测试代码似乎是多余的,但是拥有另一个分类账对于获得一种质量感是一个巨大的回报。

    2. 通过单元测试,开发人员(或配对程序员)是软件的第一个客户机。正如其他人所指出的,这就是为什么可以更快地发现bug的原因。但是,此人也是OO模型、API等的第一个客户。如果涉及到高级开发人员(执行工作或作为一对),则从设计的角度来看,质量将得到提高。这有中长期的好处。(这经常被忽视。)

    3. 良好的单元测试将暴露和练习角情况。这些情况可能无法通过开发人员手动运行的普通测试来实现。如果你想到在现场发现的错误:有多少是由于一些奇怪的情况?以我的经验,A 许多 .

    的确,在错误的情况下,单元测试就像车轮在沙地上旋转一样。但有了一些经验,即使在短期内,回报也是值得的。是的,生产代码的行数可能会更少,但错误率会更好。

        9
  •  1
  •   Patrick Cornelissen    15 年前

    当您集中精力在编写真正的代码之后甚至之前编写测试时,您将阻止自己编写过大的块。当您有很多小测试时,很可能您构造了代码以便能够编写这些小测试。

    这意味着类不需要很多基础设施来工作等。依赖注入之类的东西也很有用,因为您可能希望为测试注入模拟类。这将导致更松散耦合的类,从而提高整体代码质量并使代码更易于维护。此外,UnitTests的安全网将在软件发展过程中帮助您(不仅是在产品准备就绪之后)。

    当编码大多数(也就是全部)人时,就会产生错误。这导致小功能的开发时间更长。如果您编写测试,bug的概率会降低,如果您发现了一个bug,那么您可以确保bug的修复不会有副作用(如果您的“其他”代码的测试覆盖率很好)。这节省了很多时间,因为您不必搜索可能受上次更改影响的代码。这最终导致了更高的开发速度。

    当然,开发人员需要练习编写测试,但很快就会变得更快。尤其是如果你习惯了libs,它可以帮助你编写像easymock之类的测试。

        10
  •  1
  •   Gergely Orosz    15 年前

    从短期来看,我认为单元测试没有多大帮助,因为它只减少了一些测试时间。项目越小,影响就越小。

    然而,单元测试的好处在于,通过编写它们,您可以确保始终检测到对其进行编码的特定类型的错误。从长远来看,他们是必须拥有的,从中期来看,我会推荐他们。

    从短期来看,它们可能会降低生产率,但如果项目本身不是短期的,你肯定会从中受益。

        11
  •  1
  •   Arne Evertsson    15 年前

    单元测试从以下意义上提高了短期生产力:它使您的代码更可能更早地解决正确的问题。在创建测试上花费神经元周期将使程序员考虑该代码的不同用例和用户界面(或API)。

    相反的情况是,编写几个星期的代码,然后才意识到代码解决了一半的问题。现在你必须修补你的代码,或者甚至扔掉它重新开始。

        12
  •  1
  •   Sam    15 年前

    单元测试如何提高生产力?

    这个问题的隐含假设是单元测试确实提高了“生产力”。 如果我们将生产力定义为在工时内为给定的工作生成一个完美的可交付成果,那么更高的生产力可以解释为在少于给定的工作的情况下生成该可交付成果。 如果编码人员直接生成“完美”代码,那么进行单元测试将降低生产率。

    测试主要不是为了提高生产力,而是为了验证和验证软件实体,从某种意义上说,您正在检查是否构建了正确的产品,以及是否正确构建了正确的产品。创建和运行测试确实有副作用,最重要的是让软件创建者理解他们试图用软件解决的问题。

        13
  •  1
  •   Arne Evertsson    15 年前

    如果你说的短期意思是一两个月,我想答案是肯定的。怎样?当我需要对自己的代码进行几周没有接触过的更改,或者对团队中其他人编写的代码进行更改时,如果有单元测试并且代码覆盖率很好,我会感到更有信心。如果没有测试的话,我会更倾向于修补,四处工作,并且通常避免接触主要的算法。这样做几次,代码就会变得难以理解。

    场景:项目会议

    产品所有者:“我们需要 更改为X并添加Y特征。是 这可行吗?”.

    团队:“最好等待 乔回来了。他写了那个密码。”

    几周后……

    乔:“当然可以,但是 考虑到所有的测试 进入那个模块不是很快 “修理”。

    产品所有者:“哦。所以…让我们把更改推迟一段时间……”

    我不确定我是否在回答你的问题。这真的取决于短期有多短。;-)

        14
  •  1
  •   B T    12 年前

    现代的单元测试不是为了捕捉错误,而是为了设计和记录接口。编写测试可以帮助您思考如何使用代码,并记录它们的用途。

    单元测试可以捕获重构时引入的错误,但这通常不是项目错误的主要来源。

    因此,总的来说,单元测试将使创建质量更好的代码变得更容易(即更便宜/更快)。但它不会直接帮助你更快地完成任何给定的任务。

    阅读有关单元测试的神话和好处的文章:

        15
  •  1
  •   Dogs    7 年前

    很容易理解为什么一开始人们可能会对单元测试提高生产力的想法感到困惑。大多数人呈现单元测试的方式,自然反应似乎是 “你是说做更多的工作会让我更有效率?怎么用?“ . 这实际上是因为大多数人对单元测试有着根本的误解。当您正确地构建了单元测试的概念时,生产力的好处就会变得明显。因此,为了实现适当的框架,让我们备份并讨论角色测试(不是单元类型,而是验证程序功能的常规老想法)作为软件开发中的反馈源发挥的作用。

    我们都听过老练的资深开发人员的恐怖故事,他们说在90年代,某个被诅咒的名字曾经让整个公司离线一个星期,因为他们推动了生产的改变,但从未运行过它。有人可能会说,这里的问题是代码没有经过测试,但它肯定是经过测试的;它是在管道的最新可能阶段由最昂贵的测试人员进行测试的:客户。不需要一个专家来认识到这样的场景非常昂贵,并且通过在测试环境中而不是在生产环境中捕获问题可以节省大量的成本。更妙的是,如果解决问题意味着重做一个月的代码,那么通过识别问题可以节省很多钱。 之前 一个月的代码就被写出来了。在接下来的几段中,我将尝试通过假设的情况来传达这个概念,但是基本的思想可以概括为 较短的反馈周期比较长的反馈周期更有效率。

    伟大的。我们已经确定了一个很好的流行语来确定我们的新管理策略。工作完成了吗?嗯,不完全是。为了实现我们的“短反馈周期”,我们需要定义我们的反馈实际上是什么。假设我们在一家贷款银行工作,我们编写的代码是为银行发放的各种贷款制定分期偿还计划。这些分期偿还计划到处都在使用,它们的正确性非常重要。我们希望得到的反馈能够告诉我们,我们的代码是否为我们的贷款制定了正确的分期偿还计划,而首席执行官希望这种反馈不会以客户提出集体诉讼的形式出现,这些客户对超额收取利息感到愤怒,这是可以理解的。所以不幸的是,在我们发布代码之前,我们必须想出一种方法来确定摊销计划是否正确。

    我们可以试着辩称这就是会计部门的职责所在。所以,我们写了一堆代码,我们认为它应该起作用,然后把它发送给审计长检查。他们发现了一堆问题,然后把它发回。这似乎是公平的,因为期望像贷款软件这样复杂的东西首先会起作用是不合理的。所以我们做了一些修改,然后把它送回。但它仍然不完全完美。这个周期重复到第五或第六次,当会计部门礼貌地通知你,他们已经厌倦了你的错误代码,并且如果你再给他们发送一个糟糕的时间表,工资分类账下一个周期可能会有一些较小的数字。

    您可以获得一些样本贷款的电子表格及其正确的分期偿还计划,通过程序运行所有这些场景,比较付款和分配,确保所有内容都匹配。然而,贷款是一个复杂的领域;您可能有40个不同的场景需要测试,其中一些贷款有360个付款需要验证。运行所有这些场景需要很长时间。我们对短反馈周期、迭代设计和在过程中尽早捕获错误都有很好的想法。我们也知道,把问题分解成很小的步骤可以使问题更容易解决。我们知道重构使我们的代码更干净、更容易使用,使未来的更改更快、更轻松。 但是我们不可能花时间来验证我们所有的场景,每次我们更改几行代码。 这就是单元测试发挥作用的地方。

    如果没有单元测试,我们必须做出妥协。我们要么花大量的时间来验证我们的代码在每次更改几行代码时是否确实有效,要么我们必须延长我们的反馈周期。根据我们上面的公理,较长的反馈周期将降低生产效率。如果我们自动测试这些分期偿还计划,那么折中的任何一方都将获得生产力的提高。如果每次我们做出改变时,我们都在逐字核实摊销计划,那么生产力的好处是直接的,并且来自于消除所有的核实时间。如果我们延长了我们的反馈周期,生产力的好处是间接的,它来自于允许我们缩短反馈周期。

    从这个意义上讲,单元测试只是一个生产力工具。人们经常提到的单元测试的所有这些好处实际上都是缩短反馈周期和从这些周期中产生的迭代设计的好处。单元测试只会使这些想法切实可行。你 能够 只使用手动测试技术练习短反馈循环和迭代设计。然而,执行所有这些手动验证所涉及的开销将使这种方法完全不切实际。当你把TDD看作是重复运行程序的替代品,看看你的改变是否达到了你认为的效果时,生产率的提高真的开始有意义了。

    我的观点也有一个有趣的推论,那就是短反馈周期实际带来的好处,而不是直接进行单元测试: 完全有可能编写单元测试并从中损失,而不是从中获得生产力。 我曾在Cargo Cult编程商店工作,那里要求进行单元测试,但开发人员从未接受过适当的实践培训。在这些类型的商店中,有一些开发人员用老式的方式编写所有的代码,一旦他们认为自己完成了,他们就开始编写测试来“覆盖”他们编写的代码。然后,一旦他们改装了新的测试,他们就会推送他们的分支,并且由于没有运行任何现有的测试而使CI构建失败。然后,他们继续花费数小时的调试和修改一个分支,用一周的时间来修改他们破坏的所有测试,并在事实发生后用新的测试代码进行修改。以这种方式开发的人正在编写单元测试,但是对于他们来说,单元测试是一个额外的成本,而不是一个生产力的好处,因为他们不接受短的反馈周期。

    单元测试减少了获得反馈的时间消耗,因此您可以更频繁地进行反馈,而获得反馈更频繁意味着在“回到绘图板”的过程中损失的工作更少,复杂的问题更容易分解为更简单的问题,并且设计可以更自信地重构,以便更容易接受未来的变化。所有这些都被广泛理解为软件开发的更有效的方法,并且它们都是由单元测试允许的短反馈周期所实现的!