如果单元测试如此之大,为什么没有更多的公司在做呢?

时间:2009-02-17 17:09:47

标签: unit-testing

我工作的第一家真正的软件公司就是单元测试(NUnit)。我当时并不知道我们是真正的坚持者 - 我不知道我们的代码覆盖是什么样的,我正在编写大部分的单元测试。从那时起,我遇到了一些进行大量测试的公司,但它是主席测试:依赖于那里的人,重复性低,捕获错误的可能性低。另一种态度是:这是他们想要“未来”的事情;基本上当钱从天而降。

我想念单元测试 - 它让生活更轻松。但我发现,当我寻找新工作时,单元测试要么是公司希望在未来“开始”,要么是根本不做的事情(呃,它已经存在了一段时间)现在!)。我要说的是,过去两年我所看到的60-75%的工作要求都没有列出单元测试。我只能想到一个或两个具有单元测试经验的要求(对于中级开发人员职位)。

所以问题是,缺少什么?我认为这会让人们更有成效,但这只是在花了大量时间实际做到这一点之后。关于单元测试的成本节省是否有任何好的研究?这是我正在关注的公司类型吗?

编辑:即使标题是一个有点恶魔的倡导者,我认为自己是一个单位测试支持者。

37 个答案:

答案 0 :(得分:111)

根据我的经验,这涉及到几个因素:

  1. 管理层并不真正了解单元测试究竟是什么,或者为什么它对它们具有真正的内在价值。
  2. 管理层倾向于更关注快速的产品交付,并且(错误地)将单元测试视为对该目标起反作用。
  3. 有一种误解,认为测试完全属于质量保证的范围。开发人员是编码员,无法编写测试。
  4. 人们普遍存在一种误解,即管理层必须花钱才能正确地进行单元测试,尽管这些工具是免费提供的。 (当然,开发人员需要考虑时间,但这并不是真的令人望而却步。)
  5. Will的回答将围绕这个答案:确定测试代码的价值非常困难(编辑jcollum)
  6. 当然,还有其他因素,但这些都是我到目前为止所遇到的。

答案 1 :(得分:88)

1)很难 2)需要时间 3)确定测试代码的价值非常困难

第3点是粘性的。良好的单元测试可以减少错误。但良好的生产代码也是如此。您如何确定由于您的单元测试而不存在多少错误?你不能衡量不存在的东西。您可以指向研究,但它们并不适合您的业务经理的电子表格。

答案 2 :(得分:69)

很容易将所有责任归咎于“管理”。但是管理真的告诉你具体进行任何单元测试吗?

管理通常不会(也可能不会)告诉您如何完成工作,无论是模块化,抽象数据类型,设计模式还是单元测试。这些是成功的,有能力的软件工程师适用的交易工具,但是一个糟糕的工程师却不适用。

我认为你问题的真正答案是:单元测试真的很难,计算机科学专业的学生也没有接受过这方面的培训。

当您编写自己的字符串类时,这很容易。当您测试真实产品时,您会遇到没有人在powerpoint幻灯片中告诉您的挑战:

  • 用户互动。应用程序的一半是用户界面逻辑。如何以自动方式测试它,如果你移动一个按钮就不会崩溃?
  • 与外部API和框架的交互。如果您正在编写Windows内核驱动程序,那么如何对其进行单元测试?您是否为您使用的每个IRP和内核函数编写存根,有效地创建了OS内核的模拟?
  • 网络通信是21世纪的事情。如何协调由几个分布式组件组成的单元测试?
  • 您如何选择好的测试用例?我经常看到人们尝试“在1000次迭代的循环中做随机事情,看看它是否破坏”的方法。当你这样做时,努力高于回报,错过了重要的错误,并且放弃了单元测试。
  • 您如何测试是否符合性能要求?
  • 对测试模式的了解很少:存根,预设响应,回归测试是大多数人不知道的概念。你工作的地方有多少人真正读了一本关于单元测试的书?

我们可以归咎于管理的一件事是需求规范很少包含对交付品质量水平的任何要求。

下次你的老板要求你做一个时间估计,包括写单元测试的时间,看看会发生什么。

答案 3 :(得分:28)

大多数测试都没有测试任何东西 如果文件不存在,则编写fileopen()函数和单元测试失败,如果文件存在则成功。 大!现在你检查它是否适用于BIG5中文文件名吗?在NFS共享?在vista上,USB密钥上的文件和UAC打开?

问题在于单元测试由编写函数的同一程序员编写,使用相同的假设并具有相同的技能水平。 要真正发挥作用,测试必须由其他人编写,只有发布的规范才能看到代码。 - 在大多数公司中,获得书面规范将是一个突破!

单元测试检查各个功能的代码中的错误。它们可以用于数据访问层,数学库等,其中输入/输出是众所周知的,内部结构很复杂但是在很多情况下它们只是浪费时间。
当错误是由于代码的不同部分之间或与OS和用户之间的交互引起时,它们会失败。高/低DPI设置等问题会弄乱对话框或外语设置交换'。'通常不会找到','。

答案 4 :(得分:15)

已对单元测试的ROI进行了研究 - 请参阅this question

答案 5 :(得分:15)

我发现很多开发人员对单元测试不感兴趣。当你开始时,它似乎总是很多工作,收益甚微。没有人想报名参加额外的工作,所以他们抗拒。一旦人们开始,他们通常会热情地坚持下去,但让他们开始可能很难。

答案 6 :(得分:12)

除了采用单元测试的问题之外,单元测试并不总是值得的,尽管一般来说我认为它是正确应用的。单元测试没有什么特别之处可以使它们免于容易受到不良结构的影响。

单元测试具有成本(创建,维护和运行),只有当它们提供比这些成本更大的好处时才值得。测试创建与其他技能一样,需要特定的经验和知识才能获得成功。如果没有足够的经验,即使是经验丰富的开发人员也很容易创建低质量,低价值和/或高成本的单元测试,这些测试是不值得的。特别是考虑到单位测试的价值是多么困难。

此外,单元测试只是提高代码质量的一种方法,但这不是唯一的方法。在某些情况下,某些团队可能不是提高软件质量的最有效方法。

请记住,在单元测试中投入大量精力并不能保证高质量的软件。而且,无需任何单元测试即可生产出最高质量的软件。

答案 7 :(得分:11)

有很多公司在最佳实践方面没有做任何事情。没有代码审查,没有单元测试,没有测试计划,没有任何东西,只是在裤子的位置。

以此为契机,让他们使用持续集成平台并开发单元测试!轻松打动强大的功能,同时提高代码的质量和稳定性

编辑:至于理由,我认为他们只是很清楚当前的工具并不能让CI和单元测试非常容易。

答案 8 :(得分:11)

好吧,我的公司没有参加TDD或单元测试。说实话,我们不知道该怎么做。我们显然可以用于像CapitalizeString()这样的愚蠢函数,但我们不知道如何为具有复杂对象的高度复杂系统做到这一点。此外,大多数受访者都没有经验或经验有限。似乎单元测试在SO人群中很大,但在可用的工作池中并不是特别大。

TDD是一个单独的主题。我们在道德上反对TDD。我们不是牛仔编码员,但我们相信它会阻碍项目的创造力和灵活性。而且,编写单元测试功能的编码器没有任何意义。当我做某事时,我会对我能想到的所有边缘情况进行编码。我需要的是另一个大脑来寻找我可能错过的东西。我们没有那个。这些团队规模小而且独立。

总之,我们不相信TDD,但我们想进行单元测试。我们没有这方面的经验,我们也很难找到它。

答案 9 :(得分:6)

单元测试应该只是代码开发工作流程的一个自然部分,就像编译器一样。

但是,这需要教育管理层了解单元测试的好处。不过,初级开发者获得这种影响的机会相对较低。因此,公司是否是单元测试的支持者取决于他们是否有高级开发人员或架构师,他们是单元测试的倡导者。

我相信这是您的问题的答案“缺少什么,为什么没有更多的公司进行单元测试”。 : - )

答案 10 :(得分:5)

我不认为懒惰是不良单位测试的根本原因。对于我的公司来说,时间限制和“刚刚完成”的态度是进行单元测试的最大障碍。此外,我们的系统失败的地方往往更多地处于集成级别(服务,数据库访问,需要特定数据进行测试的复杂查询),而不是“单元级别”。这些东西更难测试,如果你没有足够的时间来完成这项功能,你可能没有时间同时完成任何有用的测试。

答案 11 :(得分:5)

我认为程序员必须开始这样做。作为开发的一部分,一些简单的测试开始很容易证明。

几乎总是需要像单元测试这样的东西才能快速调试。只需解释一下,启动测试的速度要比安排正确的输入,设置调试器断点,启动应用程序等快多少。

在您的代码中记录测试。只需发表评论,解释测试的位置以及如何运行测试。未来的程序员会看到它,希望测试能够传播开来!

答案 12 :(得分:5)

有些地方不使用它的原因仅仅是因为它需要大量工作才能开始和继续。编写单元测试所花费的时间与编写实际功能所花费的时间相似,这对于某些管理人员而言似乎正在将开发人员的工作效率降低一半。

最重要的是,您构建团队(或某人)需要将基础架构放置并维护它。

正如Alan所说,许多地方根本不使用最佳做法 - 他们只是想看到有形的东西。

答案 13 :(得分:5)

它可能是你提到的一些事情的组合。很难衡量TDD的成本节约。如果您想要外包您的IT,您可以显示您每年为员工支付的费用与签订合同的费用;它非常具体。 How do you say,“哦,这个测试抓住了一个错误,这将花了我4个小时来调试和修复......”?

答案 14 :(得分:4)

单元测试是大多数人听过的黑盒术语之一,但不知道究竟是什么构成了单元测试,从哪里开始,如何编写它们,如何实际运行测试,究竟应该是什么测试等等。

在很多情况下,不确定的开发人员更容易将它们视为不必要的或仅仅是“企业级开发人员”需要的结冰。

答案 15 :(得分:4)

我是单位测试的忠实粉丝,我也是一家公司的合伙人,负责各种客户类型的合同开发项目。在一个月内,我们将触及3-4个不同大小的不同项目。

如果一个项目看起来像是一次性的,我不会在单元测试上投入大量资金,因为单元测试不能为我的业务带来回报。在那些类型的项目中,我将对我不确定/不熟悉或可能经常更改的事物(例如我无法控制的数据源的解析器)进行单元测试。

然而,如果我正在构建一些我知道将会有更长的生命周期的东西,那么我将通过多次迭代来处理更多的工作,或者如果我将对我的客户产生巨大的影响,发生错误,我将投入更多的单元测试。同样,测试的优先级围绕不确定/不熟悉/不断变化的代码。

我认为单元测试应该围绕任务的复杂性,以及它们是否会得到回报。编写不会被使用的额外代码是没有意义的。

答案 16 :(得分:4)

从我所看到的情况来看,很多公司拥有巨大的,高度耦合的代码库,这些代码库实际上不是单元可测试的。它们也没有合适的可测试要求,因此单元测试将针对“建成的”事实要求进行测试。

答案 17 :(得分:3)

根据我的经验,这实际上取决于您正在编写的软件。我发现为UI编写单元测试非常困难。我只对系统中有明确输入/输出的部分使用单元测试。

答案 18 :(得分:3)

当然,在理想世界中,你不能反对进行单元测试。

但是,你是否编写单元测试取决于许多事情:

  • 如何使用该软件。如果你只为自己编写软件,你会编写单元测试吗?可能不是。如果您正在编写预先打包的软件以进行商业销售,可能是的。

  • 有多少人维护代码....如果它只是你,那么你可能已经知道它足够有信心在做出改变之后快速浏览代码足以确保没有任何东西破碎。如果其他没有最初编写代码的人现在必须维护它,那么单元测试将帮助他们相信当他们更新代码以修复大的时候(显然没有在单元测试中捕获!)他们没有破坏任何东西

  • 代码复杂性:只需要测试的测试代码。单行变量赋值方法不需要测试。具有多个执行路径的50行方法可能会这样做。

  • 实际的商业商业考虑因素:事实上,编写单元测试需要的时间比不这样做要长。如果您正在编写具有不确定的商业未来的原型软件,那么在快速编写代码之间有一定的回报,现在,这与在2周内运行得更好的单元测试代码相比非常有效。有时,如果软件有一个简短的架子并且继续下一个项目,那么快速找出(消费者的胃口)是值得的。

正如其他人所指出的那样,测试只能和编写它的人一样好。

答案 19 :(得分:3)

主要原因是许多开发人员和开发经理都不知道单元测试是否存在,或者如何使用它们。

第二个原因是单元测试只能用于(以合理的方式)代码已经满足某些质量标准。可能的是,某些现有的代码库不属于该类别。

第三个原因是懒惰和/或廉价。

答案 20 :(得分:3)

  

我错过了单元测试 - 它让生活更轻松。

,实际上,这是公司采用单元测试的充分理由。

一个充分的理由可能是“更便宜”(和/或“更好”):这对于单元测试来说并不那么容易。

唯一的理由可能是“编写单元测试是最好地利用开发人员的时间”,这很难证明IMO:在某些地方,某些软件,某些开发人员可能都是如此,而不是在其他地方也是如此。

有很多开发人员不认为单元测试的世界:包括一些认为其他形式的测试(例如自动集成/功能测试)可能更便宜且更有价值的人,例如Am I the only dev who doesn't like unit tests?

答案 21 :(得分:2)

与大多数好主意一样,采用更多地与组织路径依赖相关,而不是与创意质量相关。

在大多数已经发货的公司中,已经建立了一个具有高级QA负责人的大量QA部门。测试是QA团队的领导。

QA团队不太可能编写单元测试代码,因为该公司通常不会为QA团队配备重型编码员。

编程团队不愿意编写测试代码,因为它会与QA团队产生冲突。

我一直看到更多的兴趣和采用单位测试的小组,其中QA没有被分拆成一个单独的工作职能

答案 22 :(得分:2)

因为单元测试仅在编写可测试代码时才有用。编写可测试代码很难。人们懒惰和/或便宜。

编辑:细致入微的“懒惰”为“懒惰和/或便宜”;在极少数情况下,人们实际上拥有技能和能力以及编写测试的意愿,但他们还有其他事情要做,这更直接地影响了底线。

答案 23 :(得分:2)

公司没有进行单元测试,原因与许多网站写得不好 - 无知,以及人们坚持旧习惯的原因相同。 在我的公司,自从我们开始进行单元测试(使用Nunit和Typemock),我们可以在更短的上市时间内实现更高的代码覆盖率并发布软件。

答案 24 :(得分:2)

如果您想在测试中出售所有人,请执行以下操作:

  1. 写一堆测试。
  2. 通知更改代码并使测试失败的其他开发人员。
  3. 他们会修复他们的代码。
  4. 现在你可以在没有这些特殊错误的情况下发布。
  5. 即使是经理也能理解这一点。

答案 25 :(得分:2)

我认为问题的一部分是开发人员期望商人拥有相同的价值观,并真正关心“我们应该进行单元测试吗?”的答案。我们事先没有得到业务部门的批准,而是使用高级语言而不是汇编语言 - 这通常是完成工作的合理方式。

关键是,我们是唯一有资格进行调用的人(这并不是说我们所有人对该主题都有相同的知识)。此外,即使您的团队没有,作为政策问题,也不进行单元测试(或称为您当天的方法),这通常并不意味着可以'做到了。

事实是,我们无法真正证明我们所做的大多数事情的投资回报率太过细致。为什么单元测试要坚持这种不合理/非典型的证明标准超出我的范围......

答案 26 :(得分:2)

我的2美分:

  • 这需要一些教育和纪律,但新毕业生已经掌握了适当的知识。
  • 使用更好的工具可以减少测试开销,这也正在发生(重构等)

所以,这只是时间问题。

马丁 - 科普利恩的争论中鲍勃·马丁断言:

  

“现在,开发人员运送他未在单元测试中执行过的代码行是不负责任的。”

[http://www.infoq.com/interviews/coplien-martin-tdd]

答案 27 :(得分:2)

人们很懒惰,只有在被迫时才采取改变。

答案 28 :(得分:1)

简单地说,编写和更新单元测试需要花钱。大多数公司以前的软件没有单元测试,写入成本太高。所以他们没有这样做,它增加了开发过程的时间,所以他们也没有将它添加到新功能。

答案 29 :(得分:1)

我认为主要原因只是大多数管理人员和开发人员对质量不够关心。因此,他们倾向于认为编写和自动化单元测试只需要太多的努力(实际上是这样)几乎没有什么好处。

也许我们无法对这些好处做些什么,但我们应该能够通过改进相关工具来降低创建和运行测试的成本。

我发现大多数用于开发人员测试的开源工具非常原始。不幸的是,业界似乎并没有兴趣改善这种情况。

答案 30 :(得分:1)

听起来有点像AA会议。

我是一名软件工程师。

我在XMAS向我的兄弟谈论软件工程(他是商业分析师)。

  • 他一直在担任10年级学士学位 年份。
  • 谈话开始了 测试
  • 他从未见过(或听说过)自动装置 测试。
  • 甚至听说过开发者这样做。
  • 那段时间他曾为一些人工作过 大型“字母”公司,大型政府合同。

据我所知,在涉及的100位开发人员中,没有人听说过单元测试。

我的前任在我目前的工作中使用了自动验证测试,并且只进行了很少的单元测试。不用说代码需要大量重构。

答案 31 :(得分:1)

我认为为您将要使用的代码编写一个良好的单元测试覆盖率是值得的。例如,当你在一家产品公司工作时,通过编写高质量的单元测试用例,你只需要花时间投资,知道编写测试用例的所有辛苦工作都会得到回报,让你的生活更轻松。

可悲的事实是,许多软件程序员正在进行内部应用程序开发或签约,并试图将一些软件推出门外。在这些情况下,时间投入没有多大意义,因为你再也不会看到这堆代码了。

我们都可以争辩说,坚持可靠的软件开发实践是每个开发人员的责任。但是,ROI对个体开发人员来说意味着很多,对管理层来说意义重大。

答案 32 :(得分:1)

到目前为止,我已经为3家公司工作过,最近才开始编写“官方”NUnit测试,我不得不说我是一个忠实粉丝。然而,在过去的几周里我注意到了2点:

  1. 这取决于应用程序 - 某些应用程序/部分的应用程序可以非常容易进行单元测试。每次执行基本相同的功能,并产生易于识别的结果。并且有些部分不这样做:打印水晶报告或修改图像的代码块 - 这里实际上需要眼球,可能更好/更快。这些领域可能会阻止人们尝试编写测试。然后他们才开始考虑如果某些区域不能进行单元测试,为什么还要费心呢?

  2. 测试的粒度 - 许多DEV / QAs已经具备某种自动化功能来“测试”一项功能,并且对于它与单元测试的不同之处感到困惑。根据他们的测试,它可能不是。需要一些时间来欣赏的重要一点是,良好的单元测试是完全精细的。它测试了有意义的最小逻辑,这使得它可重复,自动,并且希望始终有效。我花了一点时间才真正意识到它有多么有用,特别是当你有一个庞大的代码库并喜欢在做出改变之后运行回归测试,看看你是否只是为了整个应用程序。

答案 33 :(得分:1)

大多数公司都没用。显然,不是你(或我)工作的那个。

答案 34 :(得分:1)

两件事是单元测试的障碍

  1. 一切都很难做到
  2. 没有可衡量利润的一切都很糟糕。
  3. 人类懒惰。确实是开发人员。
  4. 在我的公司(> 5.000 emp)单元测试“有”,但没有机会进行TDD或获得大代码覆盖率。要完成它很难。

答案 35 :(得分:0)

当您有一些作为服务器运行的代码时,单元测试很好(易于实现,很容易确定您已经编写了足够的测试示例)。

示例1:您应该在具有3个或更多网站版主评论的数据库帖子中进行标记 什么是测试变体

  • 查看没有评论的帖子 - >期待没有分数
  • 查看帖子并附上一条评论 - >期待没有分数
  • 查看帖子,其中包含普通用户的3条评论 - >期待没有分数
  • 查看帖子,其中包含普通用户的3条评论以及主持人至少1条评论 - >期待没有分数
  • 查看普通用户的3条评论和主持人至少3条评论的帖子 - >期待这篇文章的标记

明确的?

示例2:您有一个输出帖子列表的网站页面

我们应该如何在某些浏览器中检查此列表是否未对齐? 我们应该如何检查这个列表是否正确,我们没有粉碎样式?

没有简单的解决方案来自动化

所以在单元测试创​​建过程中的任务是理解 - 你能把代码置于服务器操作模式 - 如果你可以创建测试,如果没有那么就可以分解并创建测试片段或手动测试。

还有一件事 - 如果您有超过10-12个测试阶段而没有重大代码修改,您将获得单元测试的经济性。

此致 帕维尔

答案 36 :(得分:0)

我知道有一个人会用一个按钮查看一个表单并说“这有点过分,这应该有一个命令行界面,所以它可以在脚本中自动化”但他从来没有真正落后于单元测试。我只是不明白。对改变的恐惧可能是其中的一部分,但我已经提出要让他完成整个过程并且他已经拒绝了。

显然我现在的公司没有强制执行它们,我只是在我自己的时候写下它们。我发现在前面设置测试会导致更好/更清晰的代码,因为在考虑如何测试某些东西时,你通常不得不考虑以后的使用。