您在工作中使用单元测试吗?您从中获得什么好处?[关闭]


18

我曾计划研究并将单元测试应用到我的代码中,但是在与我的同事交谈之后,他们中的一些人向我暗示这是没有必要的,并且几乎没有好处。他们还声称只有很少的公司实际使用生产软件进行单元测试。

我很好奇人们在工作中如何应用单元测试,以及使用它们会获得什么好处,例如更好的代码质量,减少长期的开发时间等。


13
“他们还声称只有很少的公司使用生产软件进行单元测试。” 这意味着只有少数公司生产高质量的软件。您想与哪个小组保持一致?“只有少数几家公司”如何成为否定性陈述?只有少数几家公司获利丰厚;这会变得不好吗?只有少数几家公司是真正令人愉快的工作场所;这会变得不好吗?只有少数几家公司将废物的产生降到最低。这会变得不好吗?他们的“只有少数公司”的评论是毫无意义的。
S.Lott

2
它也可能不正确,有趣的是,我还没有工作或与公司未至少做单元测试的一些水平
JK。

1
我假设一个程序员认为单元测试“几乎没有好处”,或者根本不知道如何编写有效的单元测试。
Toby

该网站的开发人员使用多少单元测试?
JeffO 2011年

1
@ S.Lott:毫无意义,但是,它仍然被认为不希望进行单元测试的人不愿意做。我不是在这里捍卫他们的观点,恰恰相反。但是,该声明仍在进行,并且发表声明的人都相信它的价值,既然是这样,我们就必须说服测试抹掉它的实际好处,因为毫无意义不会对更大的事业有所帮助。
Newtopian 2011年

Answers:


20

其中一些建议我没有必要

好吧,从严格意义上讲,它们是正确的:测试,代码审查,源代码控制等也不是必须的。从长远来看,只有极少数明智的开发人员可以在没有这些开发人员的情况下工作。我们大多数人都从错误中了解了(通常是艰难的方式)为什么是最佳做法。

它几乎没有好处。

这是不是在大多数情况下都是这样。就是说,如果我们谈论的是应该在未来几年内使用的生产软件,那么在维护中。

他们还声称只有极少数的公司对生产软件进行单元测试。

可能是正确的(尽管以我的经验越来越少),但是对于单元测试的价值却无话可说。与此相反,一个古老的笑话“狗屎很好-500亿只蝇没错!” ;-)

您在工作中应用了单元测试,您从中得到什么?(例如,更好的代码质量,减少长期时间等)

十多年来,我一直在可能的情况下在我的工作中应用单元测试。对我的代码充满信心,知道它可以工作-我可以随时随地在几秒钟内一次又一次地证明它,而不是仅仅相信它-是无价的。它使我有勇气重构我的代码,改进其设计或​​修复错误,而不必担心破坏现有功能。我永远不会回到“编码和祈祷”的过去。


14

我进行单元测试,但没有(或很少)参加工作

我得到的测试的主要好处是,重构要容易得多,并且可以注意到回归(即重新引入已经修复的错误)。

测试以“构建”为生命:您在运行测试的情况下签出软件,直到所有测试都在您的修改下运行后才签入。

因此,以我的经验,以独狼的方式编写测试几乎没有用。当您总是必须调整测试以适应其他更改时,由于“他们不会让我部署”等原因,您的同事可能会删除测试(发生在我之前的工作中),等等。团队的其他成员立即受益。

当整个团队都同意时(以一个简单的团队为一组),以我的经验来看,测试对于项目的质量,样式和健壮性是很大的好处。

但是,在一个诚实地相信“只有少数几家公司会自动测试其代码”并且确信反正他们在浪费时间的团队中,似乎几乎没有希望获得这些好处的希望,但您很有可能会因此而受益。指出错误时的“时间损失”。

引入测试的最佳机会将是您自己负责的一个小项目。在那里,您将有机会发光并展示测试的价值。


1
抱歉,我听起来很消极,但我仍然被'如何将事情做得
咕unt咕burn

很好的建议。问题在于,如果做得正确,您实际上看不到单元测试的好处。仅在进行单元测试时才可能看到危害。因此,如果您需要用统计数据而不是理论来说服他人,那么您就很费劲。
Peter Kruithof

12
@keppla,我一直在团队成员以前从未听说过单元测试的项目中编写单元测试。一旦我的测试设法捕获了一些本不应该被忽视的错误,其他程序便开始引起人们的注意,很快他们便希望自己学习单元测试。具体的证据为王。
彼得Török

1
@keppla,很公平,如果队友偏向失去常识的程度,则无法通过合乎逻辑的证据说服他们:-(在这种情况下,在强大的管理支持下,您仍然可以成功地将想法付诸实践,但没有那个,就没有希望。
PéterTörök

3
您经常通过更改界面,删除类等来“破坏”测试。当您“首先进行测试”时,您不会将其视为“破坏”,而是作为“红色”的第一步。但是,当您处于“只需添加一些行,直到行得通”的心态时,测试只会多行。当被这样的人“修复”时,测试的实用性往往会下降,直到它们真正没有用。自我实现的预言4tw!
keppla 2011年

7

我倾向于支持您的同事,但仅限于此。

单元测试的问题在于,它们经常是在琐碎的情况下写的,而这些例子在粗略的案例中粗略地研究了一下,发现无论如何它都会起作用。例如:

def add(x, y)
  x + y
end

伴随一打测试,以确保添加的内容确实适用于任意选择的用例。h ...

单元测试的基本前提是:如果您的代码中没有错误,那是因为您没有进行足够的测试。现在,何时编写适当的单元测试。答案:

  1. 在测试时
  2. 调试时
  3. 当您开发非常棘手的东西时

假设您正在开发某种fo网络应用程序,让我们仔细研究一下每个应用程序。

您为新功能编写了一些代码,并且现在应该可以正常工作了。然后,您可以通过浏览器进行更深入的测试来验证浏览器是否正常工作,对吗?Bzzzt!...错误的答案。您编写一个单元测试。如果您现在不这样做,那么您可能永远也不会这样做。这是单元测试很好运行的地方之一:测试高级功能。

然后,您会发现一个错误(谁不会错过任何错误?)。这使我们指出了第二点。您将回到代码中并开始执行以下步骤。这样做时,请在关键的断点处编写单元测试,在这些关键点上,保持一致和正确的数据至关重要。

最后一点是相反的。您正在设计一些繁琐的功能,其中涉及大量的元编程。它会迅速生成具有数千种潜在方案的决策树,并且您需要确保它们中的每一个都能正常工作。在编写此类内容时,在这里或那里进行简单的更改可能会在食物链的下游产生难以想象的后果。假设您正在设计使用SQL触发器的MPTT实现-使其可以与多行语句一起使用。

在这种棘手的环境中,您通常会希望高度自动化测试。因此,您可以编写脚本来自动生成测试数据,并对该测试数据进行大量单元测试。执行此操作时不要忘记的关键一件事是,您还需要为单元测试生成器编写单元测试。

底线:单元测试,肯定是的。但是,请避免使用基本功能-直到您真正需要它们进行调试,或者确保某些功能丰富的功能正常工作为止(在后一种情况下,包括测试本身)。


正如肯特·贝克(Kent Beck)所说:“测试所有可能破坏的东西。”
彼得Török

1
全心全意地同意他的意见。我的主要希望是OP会注意:不要忘记在适用的情况下测试测试。:-)
Denis de Bernardy 2011年

7

所有代码都必须经过测试。别无选择。

未经测试的代码是无用的:它不能被信任做任何事情。

您可以编写单元测试,也可以希望编写更高级别的集成测试或验收测试。

单元测试更易于编写,调试和管理。

集成测试基于单元实际工作的假设。没有单元测试,您如何知道单元工作?如果您不知道要集成的各个单元是否实际工作,该如何调试集成测试?

同样,验收测试取决于所有工作的零件。如果没有一套单元测试,如何知道零件和零件的工作原理?

测试是强制性的。所有更高级别的测试均取决于实际工作的单元。

这使得单元测试成为必然。别无选择。


1
没有其他选择...如果您关心质量。大多数软件组织并不真正关心质量(到目前为止,他们拒绝交付已知已损坏的软件)。
Joeri Sebrechts

@Joeri Sebrechts:这不是质量问题。这是一个“完成了”的问题。即使是不良的软件也需要进行测试,以证明它可以执行任何操作。简单的逻辑表明必须进行测试以证明其有效。即便是不好的测试也是一种测试。简单的逻辑表明,对整体的测试必须包括对零件的测试。逻辑仅要求进行单元测试,仅此而已。不是质量方面的考虑,而是“完成”的定义。
S.Lott

1
使用该软件本身就是一种测试。许多组织都很乐意让用户进行测试。我并不是说那是一件好事,但事实就是如此。实际上,您可以选择不交付前进行测试,而将测试转移给最终用户。可以,但是不可以。
Joeri Sebrechts

1
@Joeri Sebrechts:其实不能。您不能将软件(随机地)交给用户进行验收测试。您必须至少运行一次该软件,以确保它似乎可以运行。那是一个测试-一个糟糕的测试-而是一个测试。从逻辑上讲,该不良测试包含了不良的单元测试。它们存在,即使它们非常糟糕。
S.Lott

您对单元测试的定义对本次讨论毫无用处。单元测试是经过整理的测试,对于软件发布完全没有必要。(但在很多情况下都可以做得很好)
马丁·巴

6

我对编写的所有内容均使用单元测试,并且在没有测试用例的情况下,请勿让任何未经测试的代码通过审查。(但是我缺少覆盖率工具,因此我不得不考虑测试覆盖率。一次一件事……)

这很简单:如果您无法证明自己的代码有效(以及比测试形式的可执行文件规范更好的方法?),那么它将无法正常工作

这给了我:

  • 放心:我的CI服务器告诉我我的整个代码库都能正常工作。
  • 改进代码的能力:知道重组后我什么都没破坏,因此我可以重组代码-对其进行重构。

2
我要特别指出的一点是,仅单元测试不能保证“您的整个代码库都能正常工作”。这将确保在隔离代码工作的所有单位,但仍然对集成错误,在数据的视觉呈现等错误了巨大的可能性
瑞安布伦纳

除非您的环境经过“如果您无法证明代码不起作用,那么它就起作用”。:p
Davy8

@Ryan:当然,您的集成测试应该驱动整个项目。问题是关于单元测试的,所以我谈到了单元测试,但是当然,您应该通过失败的集成测试来证明对一段代码的需求。当然,您应该有一个CI服务器自动部署代码库并运行所有测试l
Frank Shearar 2011年

@ Davy8:在这种情况下,您会遇到“单元测试有效吗”的更严重的问题。
Frank Shearar

4

单元测试是一门学科。因为不需要代码工作,所以通常将其丢弃。

但是,这是一种行之有效的方法,可导致健壮且错误较少的代码。正如您已经提到的,我认为我不需要向您解释好处。如果您查看一些领先的开源项目,无论它们是JavaScript库,全栈框架还是单一用途的应用程序,它们都使用单元测试。

我怀疑建议不要使用它的同事不是程序员。如果是的话,那么我们可以说没有比Martin FowlerKent Beck等人更有价值的人了;)。

与大多数最佳做法一样,好处是长期的,您需要花一些时间。您可以编写很长的程序代码脚本,但是我们都知道,当您需要在2年后对其进行重构时,希望以面向对象的方式编写它。

单元测试也是如此。如果您为应用程序中的关键部分编写单元测试,则即使在重构代码之后,也可以确保它始终如期运行。也许您的代码编写得如此出色,以至于您永远都不会遇到回归错误。但是,如果您没有这样做,或者新程序员加入了您的团队,那么您想确保过去的错误不会再次发生。我认为您的老板也会对此感到满意,而不是不得不提交他认为已经在半年前解决的错误报告。


3

单元测试需要对单元测试友好的语言,对单元测试友好的设计和对单元测试友好的问题。

C ++,多线程设计和GUI将是一场噩梦,问题的覆盖范围将令人震惊。

.NET,可重用的单线程dll程序集,纯计算逻辑将轻而易举。

值得,我不能说真的。

您重构很多吗?您在代码中是否经常看到“笨拙的错误”之类的“笨拙的错误”?

无论您做什么,都不要以“没有单元测试,因此很烂”来批评别人。如果测试对您有所帮助,那就去吧,否则,就好像它们不是灵丹妙药。


1
为什么多线程设计会成为噩梦?设计同步点,并在那里进行测试。
Frank Shearar 2011年

1
因为时间取决于月相,CPU时钟,废纸and和几乎所有东西。如果您很幸运,那么在一次入住中,测试可能会失败,在另外1000次中,它不会。
编码器

1
我已经写了测试驱动的多线程的东西。这绝对是可行的。
Frank Shearar 2011年

4
垃圾,您可以使用任何语言进行单元测试。
jk。

1
很难编写用于GUI交互的单元测试,但这就是为什么我们隔离任何与GUI无关的内容(我们的引擎代码)的原因。它帮助我们做出了一个很好的决定,将引擎与GUI分开,此外,单元测试代替了GUI成为我们的界面,询问并提供了我们通常需要的信息。
机遇

3

,但是我不幸的是,几乎所有的公司都只在那些不在乎质量的公司工作,而他们更专注于将垃圾整理起来,这在某种程度上是可以的。我已经提到单元测试,并且得到“呵呵”。外观(当我提到SOLID原理或ORM或“除所有静态方法的类之外”或遵循.NET命名约定以外的设计模式时,会得到相同的外观)。我只去过一家了解这方面知识的公司,但不幸的是这是一份短期合同,该部门已裁员以削减成本,因此没有足够的时间来真正学习。

我曾涉足一次性虚拟项目中的单元测试,但是我并没有真正了解成熟的TDD / BDD,也没有一位导师可以帮助您解决这个问题,因此很难正确地完成它。


2

我们使用它们。我们获得的一大好处是,我们的单元测试框架可以检查内存泄漏分配失败。有时问题出在单元测试代码本身中,但通常出在生产代码中。

这是查找代码审查中遗漏的那些东西的好方法。

单元测试(应该)也非常快地运行,并且可以在每次提交后作为持续集成的一部分运行,也可以由开发人员在提交之前进行。我们有1,000多个,运行时间不到20秒。

与之相比,系统级自动化测试需要40分钟以上的时间,而人工测试则需要数小时/天的时间。当然,单元测试不是您应该做的唯一测试,但是在细粒度的代码级别,它们可以帮助发现错误并测试系统/集成测试无法触及的那些极端情况。我们的代码必须以超过75%的决策覆盖率和100%的功能覆盖率进行测试,如果没有单元测试,这将很难实现。


2

我会说单元测试确实可以增加价值,但是我不是TDD的大门徒。当我使用calc引擎或任何类型的引擎,然后使用实用程序类时,我发现单元测试的最大好处就是单元测试非常有用。

我更喜欢使用自动化集成测试来处理更多依赖数据的块,但这完全取决于我在数据行业中的工作,因此与我们相比,与我们的环境中的数据相关的错误更多,并且自动化集成测试效果很好。前后检查数据并从这些测试生成异常报告。

因此,单元测试确实可以增加价值,特别是如果可以为您要测试的单元提供所需的所有输入,并且可以使用给定的输入单独工作。同样,在我的情况下,calc引擎和实用程序类是这些的完美示例。


2

成本:编写代码较慢,学习曲线图,开发人员惯性

好处:通常,我第一次测试时发现自己编写了更好的代码-SOLID明智...

但是,恕我直言,我认为最大的好处是在经常变化的大型系统中具有可靠性。当您发布多个版本时,良好的单元测试将节省您的屁股(不是我的),并且可以消除与手动质量检查流程相关的大量成本。当然,它不能保证没有错误的代码,但是会捕获一些难以预测的代码。在大型复杂系统中,这确实是一个很大的好处。


0

有机会时,我会在工作中进行一些单元测试,并试图说服同事也这样做。

我并不是很虔诚,但是经验表明,作为单元测试的实用程序和业务方法非常健壮,并且在测试阶段几乎没有或几乎没有bug出现,最终降低了项目成本。


0

我看到对单元测试进行编码和使单元测试执行成为日常构建过程的一部分的真正优势是在一个项目中,该项目有30多个开发人员在3个不同的大陆工作。单元测试真正闪耀的地方是某人在不了解人们如何使用该类的情况下巧妙地更改了他们所维护的类。当其他人的单元测试由于更改而开始失败时,可以立即得到反馈,而不必等待代码进入测试组。[这就是为什么所有单元测试都需要定期运行的原因,而不仅仅是您为代码编写的测试。]

我的单元测试准则是:

  1. 测试您可以为代码想到的每个条件,包括错误的输入,边界等。
  2. 所有模块的所有单元测试应定期执行(即作为夜间构建的一部分)
  3. 检查单元测试结果!
  4. 如果有人发现您的代码中的错误超出了您的测试范围,请为其编写新的测试!

0

我最近学习了TDD,发现它非常有用。它使我的代码表现出了我所期望的更大的信心。除了进行任何重构外,我还希望这样做更容易。每当发现错误时,您都可以通过测试确保它不会再次出现。

最难的部分是编写好的单元测试。

这是您代码的良好基准。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.