通常认为(至少在Stack Overflow上)应该一直进行单元测试,并且应该保持最新状态。但是我怀疑做出这些断言的程序员可以在我自己的不同类型的项目上工作-他们在高质量,持久耐用的出厂软件上工作,这些软件中的bug真是一件很糟糕的事情。

在单元测试最有价值的领域,那么另一端呢?单元测试最不有价值的地方在哪里?在什么情况下您不会打扰?维护测试的努力在哪里不值得付出代价?

评论

“ [在Big Ball Of Mud类代码中] ...单元测试的工作方式与我在良好代码中的使用方式相反,例如破坏合理的更改并未能捕获我犯的真正错误。这很痛苦,但并不令人惊讶-从设计不良的测试单元开始,还有什么期望?不是帮助您改进设计,而是通过单元测试来保存错误的代码...”-我在另一个答案中写道

@gnat取决于测试的方向。当深入研究细节并在实现后编写时,单元测试特别脆弱,因此单元测试成为徒劳的追赶练习,因此维护成本非常高昂。使用明智的重构对遗留代码进行有针对性的测试可能会有所帮助,但只能在一定程度上有所帮助。 OTOH是一个绿色行为驱动的项目,倾向于导致测试保留要求而不是测试,因为更改的要求需要删除不再符合要求的较旧的不合适测试。

@ S.Robins听起来像您喜欢绿色行为驱动项目中的单元测试。如果是这样,那么我在这里与您有200%的关系;在这种情况下,单元测试尽可能地接近银弹。而且,是的,根据不断变化的需求进行测试很有趣-当了解到一切后,白盒测试很酷

这个问题提出了类似的结论,结论是不值得为他们做,因为以后他们会得到报酬来修复错误:programmers.stackexchange.com/q/64592/1249

哦,从“你应该”开始的答案的喜悦...

#1 楼

在以下情况下,我个人不会编写单元测试:


代码没有分支是微不足道的。返回0的getter不需要进行测试,并且其使用者将通过测试来覆盖更改。
代码只需传递到稳定的API中即可。我以为标准库可以正常工作。
代码需要与其他已部署的系统进行交互。那么就需要进行集成测试。
如果成功/失败测试很难量化以至于无法可靠地测量,例如隐写术对于人类来说是不明显的。
如果测试本身比代码难编写一个数量级。
如果代码是一次性代码或占位符代码。如有疑问,请进行测试。


评论


总的来说,我同意+1。但是,关于#1:无分支代码不一定非要琐碎,即使当前是由于幸运的情况造成的,预期的行为仍然可以进行测试。

–user7043
2012年5月3日12:32



如果测试本身比代码难写一个数量级。其实我大多数时候都会有这种感觉:P

– Songo
2012年5月3日,12:34

@CarlManaster我认为这就是重点。如果很难编写一个测试用例,那么就很难理解,并且很可能在程序中创建许多错误。诀窍是如何避免此类方法。

–尼尔
2012年5月3日14:41

+1用于集成测试而不是单元测试。如果要从外部系统进行交互/检索数据,那么它实际上会适得其反,并且可能会引入错误,从而导致使用“模拟”的独立测试成为可能。

– noahz
2012年5月3日15:04

“代码需要与其他已部署的系统交互;然后需要进行集成测试。” -这就是模拟对象的用途

– BlueRaja-Danny Pflughoeft
2012年5月3日15:41

#2 楼

除非您不进行测试就编写代码,否则总是要承担测试成本。

进行单元测试与不进行单元测试的区别在于编写测试的成本之间的区别与手动测试相比。

如果编写单元测试的成本为2分钟,而运行单元测试的成本实际上为0,但是手动测试代码需要1分钟,然后如果您两次运行测试,您甚至会收支平衡。


多年以来,我一直误以为我没有足够的时间来编写代码我的代码的单元测试。当我确实编写测试时,它们是肿的,沉重的东西,这仅鼓励我认为我应该只在知道需要它们时才编写单元测试。

最近,我一直被鼓励使用Test驱动开发,我发现这是一个完整的启示。现在,我坚信我没有时间不编写单元测试。

根据我的经验,通过考虑测试进行开发,最终会得到更简洁的界面,更集中的类和模块和通常更多的可测试的SOLID代码。

每次我使用没有单元测试的旧代码,而我必须手动测试某些东西时,我一直在想:“如果该代码已经进行了单元测试”。每次我不得不尝试在具有较高耦合度的代码中添加单元测试功能时,我总是在想:“如果以非耦合方式编写,这将变得更加容易。”

比较和对比了我支持的两个实验站。一个已经存在了一段时间,并拥有大量的旧代码,而另一个则相对较新。

在向旧实验室添加功能时,通常是下手实验室并花费大量时间来研究其所需功能的含义以及如何在不影响任何其他功能的情况下添加该功能的情况。根本没有将代码设置为允许离线测试,因此几乎所有内容都必须在线开发。如果我确实尝试离线开发,那么最终我会得到比合理数量更多的模拟对象。

在较新的实验室中,通常可以通过在办公桌旁离线开发功能来添加功能,仅模拟那些需要立即执行的操作,然后仅在实验室中花费很短的时间,以解决所有未脱机处理的剩余问题。


TL; DR版本:

写测试的时间和编写测试的费用加上所需运行次数的成本相比,可能会比手动测试次数高

请记住,如果您使用TDD,编写测试的成本可能会随着性能的提高而降低,并且除非代码绝对琐碎,否则您可能最终会运行测试次数超出您的预期。

评论


就是这个!我有些同事不时地说:“我已经完成了工作,但是现在我必须编写一些单元测试。”这些单元测试通常最终变得肿,笨拙且难以维护。

–太平鸟
2012年5月3日21:16

伙计,你说的是我的想法和我的经历。最近,我只是硬着头皮,为单元测试编写了一些旧版API的模拟对象,因为将代码上传到服务器,进行部署和测试大约需要10分钟。

– Alvin
2012年5月3日23:40

好的,但是您的答案是“ TDD很棒!”我的问题是“什么时候不编写单元测试?”您真的不会在不适合进行单元测试的地方进行任何编码吗? (也就是说,忽略您希望但不能的情况。)

–史蒂夫·贝内特(Steve Bennett)
2012年5月4日在8:02

@SteveBennett-我回答第一部分,如果手动测试的成本非常低和/或编写测试的成本非常高,则您不编写测试。 TDD通过降低编写测试的费用和运行测试的例行程序,有助于改变涉及的经济学。希望我在最后添加的摘要可以使这一点变得清楚。

– Mark Booth
2012年5月4日晚上8:40

@ k3b-确实,但是,如果您处于新的需求变更周期中,则将有新的手动测试成本以及单元测试更新和代码更新成本。除非需求发生变化,否则您无需更改单元测试,并且如果代码更新破坏了测试,则您需要根据那些需求来了解哪个破坏了,测试还是代码。进行单元测试的优点之一是,您可以看到由于需求变化而导致的代码更改何时具有意外的副作用。否则,直到为时已晚,这些副作用才会被发现。

– Mark Booth
2012年5月4日10:05



#3 楼

就我个人而言,我通常不为以下内容编写单元测试:


更改现有的非单元测试(旧版)代码。从理论上讲开始单元测试永远不会太晚,但实际上,将单元测试添加到从未进行过TDD的代码中所获得的收益很小。唯一的好处是可以防止回归。您可以查看更改对您可能会或可能不会影响的区域产生的影响。但是,单元测试只能证明代码仍然可以像编写测试时那样工作。因为测试不是基于原始要求编写的,所以该测试不能证明当前的实现是“正确的”。在我的经验中,对这样的代码库进行单元测试的更改甚至是噩梦,然后再进行更改并手动执行程序的受影响区域。您首先必须为有问题的代码编写适当的单元测试(这可能需要重构代码以允许模拟和其他对TDD友好的体系结构),证明它已通过并且重构没有破坏任何内容(当这是第一个针对百万LoC代码库编写的单元测试,这可能很困难),然后更改测试以期望有所不同,然后更改代码以使更改的测试通过。
UI布局和顶级行为。在某些情况下,这是不可行的。许多带有“设计者”的IDE都将UI元素声明为私有的,从概念上讲,它们不应公开。使它们内部化将需要将单元测试与生产代码置于同一程序集(错误),并使它们受到保护将需要“测试代理”,该代理公开了我们需要了解的控件知识(通常也不是其完成方式)。即使可以公开所有控件并因此可以访问它们的类型,位置,格式属性等,验证UI的测试还是非常脆弱的。通常,您仍可以在codebehinds / viewmodels中对事件处理程序进行单元测试,然后证明单击按钮会触发处理程序很简单。
数据库持久性。根据定义,这是一个集成测试。在处理将数据传递到存储库的代码时,您总是会模拟存储库,而在存储库本身中进行开发时,则会模拟ORM的挂钩。虽然有“数据库单元测试”,并且您可以使用SQLite之类的“模拟”数据库,但我发现这些测试永远无法适合单元级别。
第三方代码。您可以按自己的意愿测试代码,并相信所使用的第三方工具的开发人员(包括.NET Framework本身的组件,例如WPF,WCF,EF等)的工作正确无误,直到证明错误为止。证明您进行了正确的WCF调用的单元测试不需要实际越过服务代理,并且没有必要测试特定的WCF服务调用在单元测试中是否正常工作(是否起作用取决于特定于环境的变量)在本地测试环境中可能是完美的选择,但在构建机器人或QA,Staging或UAT环境中则不是最佳选择;这是更高级别的集成,AAT和手动测试仍然有价值的地方。

在几乎所有其他情况下,测试优先方法在执行需求和YAGNI,防止回归,识别需求冲突等方面都具有重要价值。即使在“琐碎”代码的情况下,验证“是的,此属性仍会返回此”。价值,因此您可以相信在其他测试中”对于开发人员来说对我来说是有价值的。

评论


另一种情况:一种例程,它返回随机的东西,尤其是复杂而随机的东西。这在商业世界中非常罕见,在游戏世界中,很多程序中都会包含此类例程。

–Loren Pechtel
2012年5月5日,0:50

-1。如果您不为现有代码编写测试,那么您如何对自己的代码有信心?您的代码覆盖率为0%,或者对现有代码的工作能力完全没有信心。

– CodeART
2012年5月5日14:28

如果我在旧版代码库中工作,那么它的代码覆盖率已经为0%。我有信心吗?嗯,通过并购,公司的三个迭代中已经使用了几个主要的内部应用程序,所以我不得不说是。尽管将单元测试添加到这些代码库中是回归的一个崇高目标,但这些测试仅证明该代码以始终具有的相同方式工作,而不一定表明结果是“正确的”。我支持我的原始声明,但进行了编辑以阐明具体情况。

– KeithS
2012年5月7日15:52

@CodeWorks:我倾向于同意OP。是的,添加单元测试是一个好主意,但是在事实发生之后添加它们(重构,框架设置等)会产生初始成本。如果仅作一些小改动,则可能无法证明工作合理。

–sleske
2012年5月9日在8:25

是的,但是现在您要更改类的定义方式,除了能够测试它之外,没有其他原因。为此您要进行的大多数其他更改在其他地方都具有价值,例如注入依赖项。我并不是说这样做是错误的方法,也不是说我提到的方法更好,但是您必须权衡每种方法的利弊,尤其要考虑要包含的成本(您是否确实需要对单击按钮时调用事件处理程序的单元进行测试(真的吗?)。

– KeithS
13年2月8日在15:41



#4 楼

在编写单元测试的成本和它们增加的价值之间需要权衡。忽略此风险可能会导致过度测试。

blueberryfields提到了一个会影响单元测试价值的变量:项目的稳定性(或开发进度)。我想在此基础上进行扩展。

进行单元测试的价值大致遵循以下图表(是的,MS Paint!):





在第一个区域中,代码不稳定到经常需要重写或完全废弃单元测试的地步。这可能是您不会使用的原型。或者它可能是您不熟悉编程语言或框架(并且经常需要重做大量代码)的项目。

单元测试非常适合在模块级别进行重构(即更改职能)。问题是,当代码在体系结构级别不稳定时,可能会重写,删除或完全重新设计整个模块。然后必须更改/删除/添加单元测试,这是一个负担。

在此阶段,限于系统级集成测试,甚至手动测试是一种更好的方法(您再次选择该方法)取决于编写测试的成本与获得的值)。

单元测试在第二个区域中增加了最大的价值,在该区域中,代码在模块级别之上变得稳定,但尚未达到模块级别。如果您有稳定的代码库,并且要添加一个很可能留下的模块,那么这就是单元测试大获胜的时候。

当稳定性很好时,单元测试的价值也开始降低。被测代码的数量很高。测试标准库函数的简单包装器就是单元测试过大的一个例子。

如果您正在编写的一段代码可能永远都不需要更改,并且您确信它已经做到了对(也许这很简单?),测试的价值较小。


当效用大于成本时,单元测试将变得有益,如下图II区所示。



对于不同的成本,此成本线可能处于不同的水平人(第1行与第2行)。如果您不熟悉项目中使用的测试框架,则可以提高水平,并减少网络实用程序。较高的成本(第2行)缩小了适用于单元测试的范围。

成本线不一定必须保持不变。特别是当您考虑其他变量(例如项目规模)以及该项目是否已经存在测试框架时,情况可能就是如此。

评论


很好的答案-测试对于要求未知的快速发展的项目以及代码非常稳定的缓慢发展的项目而言,价值最低。鉴于我的大部分工作都在前者中,所以这与我联系在一起-但也表明我们需要在情况稳定时进行测试。

–史蒂夫·贝内特(Steve Bennett)
2012年5月6日15:14

实际上,测试可以帮助快速发展的项目-但您必须对测试内容更加谨慎。在尚未确定正确结果是什么的情况下,您无法进行测试:-)。

–sleske
2012年5月9日在8:56

@sleske:是的,但是快速发展的项目往往缺乏可以进行单元测试的特定(稳定)要求。通常,已知的只是更高级别的要求,这些要求更多地用于集成测试。

– jamesandlund
2012年5月9日17:43

这是一个出色的答案。它以衡量和注重结果的方式解决了选择测试策略所涉及的权衡问题。

–本杰明·霍奇森(Benjamin Hodgson)
2014年9月28日在21:39

#5 楼


单元测试最有价值的地方在哪里?


您应该只为逻辑代码编写单元测试。逻辑代码的定义如下:

逻辑代码是其中包含某种逻辑的任何代码,
可能很小。如果它具有以下一项或多项内容,则它是逻辑代码:IF语句,循环,开关或case语句,
计算或任何其他类型的决策代码。


如果那是单元测试最有价值的领域的尽头,
那另一端是什么?



紧密耦合的代码无法轻松测试。有时根本无法测试。例如,ASP.NET Web表单是一场噩梦,有时甚至无法测试,这与考虑到单元测试的ASP.NET MVC相反。
我可能选择不为非常小的和简单的项目编写测试。在时间和资源有限的情况下,这是完全合理的。是的,这是有风险的,但是当您工作的公司上市时间有限时,这是完全可以接受的。


什么情况下您都不会打扰?
维护测试的努力在哪里不值得花费?具有高代码覆盖率的单元测试为您提供了一种宝贵的信心,使您对系统的行为充满信心。集成测试也是如此,但这不是您的问题。

我的回答基于以下假设:


您知道单元,集成和集成之间的区别。功能测试。
您精通其中一个单元测试框架,并且编写单元测试的工作量很小。
编写单元测试时,您不会觉得自己在做额外的工作。

参考:单元测试的艺术

评论


这个答案(根据问号)确实会受益于不是“逻辑”的代码示例(例如:函数/类/ ...)。

–马丁·巴(Martin Ba)
2012年5月3日,11:41

自动属性不是逻辑的,除非它在内部封装了一些逻辑,即if / else语句。

– CodeART
2012年5月3日,11:56

您想量化“非常小而简单”吗? <500行?

–史蒂夫·贝内特(Steve Bennett)
2012年5月4日在8:07

另外,感谢您阐明“您精通单元测试框架之一”的假设。这一直是我的杀手.。最近的一个(相当小的)项目要求我学习nodeJS,Underscore,Atom,Handlebar和我忘记的其他技术。测试框架是Vows,这是太多的障碍。

–史蒂夫·贝内特(Steve Bennett)
2012年5月4日晚上8:09

对我来说,小型而简单的是一个代码库,我可以在30分钟内完全理解它。我确实看到你的意思。

– CodeART
2012年5月4日晚上8:11

#6 楼

肯特·贝克(Kent Beck)(单元测试的概念背后的人)说,在可能会扔掉的想法(例如原型)上工作时,如果不决定继续工作,最好不要编写单元测试。相反,如果您编写原型并决定继续使用它,则由于先前答案中提到的所有原因,单元测试将非常有用。

#7 楼

您确实应该对打算多次运行的任何代码进行测试。

如果打算运行一次然后将其丢弃,则测试可能没有用,尽管如果域是复杂的情况下,我还是应该编写测试来帮助我进行设计和实现。

否则,即使测试所做的唯一事情就是确认您的假设仍然正确,但它们是有价值的。持续时间超过单个会话的任何代码都需要进行修改,这时测试将为自己支付10倍以上的费用。

评论


对于有人为什么不赞成这篇文章的见解,我深表感谢。

–比尔·米歇尔(Bill Michell)
2012年5月3日13:38

并没有否决权,但我想提出一个观点,即所有代码都必须经过测试,这是出于宗教的考虑,并非总是可行的。

– noahz
2012年5月3日15:03

@noahz是的,我会买的。但是在“必须,应该,会”的规模上,我选择了“应该”而不是“必须” ...

–比尔·米歇尔(Bill Michell)
2012年5月3日在16:34

好的-但是,如果代码“需要修改”,则测试也将花费更多,对吗?另外,您是否测试shell脚本?构建脚本?

–史蒂夫·贝内特(Steve Bennett)
2012年5月4日在8:04

是的,我测试了这些脚本。它们不能用单元测试进行测试,但是仍然可以进行测试。

–比尔·米歇尔(Bill Michell)
2012年5月4日13:47

#8 楼

我对不必要的内容毫无头绪,但是当我认为单元测试不合适时,我会去争取,因为它们会增加成本而没有成比例的收益:

如果我们的组织/开发团队未进行任何单元测试,然后,除非您能够说服其他开发人员运行,修复(并自行创建)单元测试,否则将不会运行和维护您创建的测试。 (这意味着您正在与其他人一起开发软件。)

并非每个人都在进行单元测试,它们有时会受到本地团队文化的支持,而在这种环境下,您首先需要在实际开始编写单元测试之前,对大多数开发人员以及可能在构建过程(“ [连续]集成”)中使用它们,都是有意义的。

考虑到时间压力和交付日期和“您”在团队中的相对地位-编写单元测试有意义的剩余时间很容易就可能是数月或数年。

评论


+1表示维护问题。尽管我已经成功地使用了单元测试作为唯一使用它们的开发人员。只是,当我在另一个项目上待了几个月时,花了几周的时间才使所有单元测试再次起作用...

–sleske
2012年5月9日晚上8:58

#9 楼

有时您没有时间进行单元测试。没关系。

存在外部约束,并且您可能不会在给定的时间内感到需要进行测试,因为您可能认为自己对整个系统状态有了牢固的了解,并且知道更改将如何波动。

,但我仍然相信您对此应该感到内。
所以当事情开始崩溃时,您会知道这是因为:“哦,是的,我没有测试东西,让我们开始测试。“

在那一刻之前,内的感觉将帮助您避免某些体系结构的选择,这些选择会阻止您稍后再执行代码测试。

评论


…顺便说一句,我现在感到内gui。

– ZJR
2012年5月3日在16:38

您没有时间进行单元测试-庞大的BS。因此,没有时间进行单元测试,但是总是有时间修复错误。

–BЈовић
2012年5月3日19:38

tru,@ VJovic。但是如果OP并没有真正感到需要测试,因为没有测试仍然没有烧死他,只是出于盲目的做事。好吧,那我想那会变得更糟,因为出于盲目的信仰而做事会使您陷入非常奇怪的角落。

– ZJR
2012年5月3日在20:23

实际上,我不进行单元测试的原因不是没有时间-通常是因为我不知道代码将如何很好地进行说明,或者我对技术不够了解,因此学习和部署测试框架将是额外的负担。

–史蒂夫·贝内特(Steve Bennett)
2012年5月4日晚上8:06

需求编码是TDD中的关键。您应该有某种文档来告诉您在特定情况下代码应执行的操作(这可能很简单,例如“当我单击此按钮时,我希望进入页面X”,PD,GAAP会计准则以及通用表示为“我们需要一个将接收这些文件并产生此输出的系统;继续执行”。如果您对特定区域的需求不够细致,无法编写可反映这些需求的单元测试,则您必须根据所知道的内容进行插值。如果您甚至不能做到这一点,那么您需要更多的要求。

– KeithS
2012年5月7日16:08

#10 楼

代价不是维护测试,而是维护工作代码。如果您离婚了测试和实施,则假定您编写的内容将在没有证据的情况下起作用。测试为您提供了证明,并为您提供了随着时间的流逝维护代码的信心。当然,您可能会认为您永远不会再访问曾经认为是一掷千金的应用程序,但是事实是,您花费任何时间编写软件都是您的雇主不希望轻视的投资。面对现实吧,软件开发人员通常并不便宜,花在代码上的时间只是浪费了雇主的钱。

如果您遇到问题,请写几行代码看看某个东西是如何工作的,或者简单地为Programmers.SE编写一个示例,那么这是创建满足您对问题的了解后完全打算扔掉的东西的情况。在这种情况下,单元测试可能会阻碍任务执行,并可以安全地排除在外。但是,在所有其他情况下,即使程序看起来相对不重要,我仍然认为测试始终是适当的,并且您应始终以编写具有足够测试支持的专业标准为目标,以减少维护代码的难度。未来。

评论


测试不能证明代码可以正常工作,它们可以向您证明它们在测试正确的前提下不会失败。

– dan_waterworth
2012年5月3日10:55



如果您不认为我的评论使您的观点无效,那么您就不会理解我的评论。测试不能证明正确性,但是您会说“测试为您提供了证明[您编写的内容将起作用]”的声明。

– dan_waterworth
2012年5月3日,11:22

澄清一下,证明一词具有明确的含义,我理解有效的代码是指可以毫无例外地执行其意图的代码。我将使用交互式校对助手来创建校对。测试可以提供保证,但是除非提供详尽的模型检查,否则它们无法提供代码有效的证明,而这几乎是不可能的。

– dan_waterworth
2012年5月3日,12:04

上下文是软件。如果我要求提供正确性证明,则不要使用测试套件。

– dan_waterworth
2012年5月3日12:59

@ S.Robins,您完全忘记了要点。如果我想编写可证明的正确软件,则可以使用依赖类型的语言或其他形式方法。正如我已经说过的,“手工检查和昂贵且记录繁重的Q / A系统”是测试的形式,但不能证明其正确性。

– dan_waterworth
2012年5月4日10:00

#11 楼

在一个项目中要进行的单元测试的数量和质量与开发速度和产品所需的稳定性直接成正比。

一方面,对于一次性脚本,简单的演示,或者在非常早期的快速启动环境中,单元测试不太可能对任何事情都有意义或有用。几乎可以肯定,它们几乎总是在浪费时间和资源。

另一方面,编写控制起搏器或飞行员的软件时,或者在保持稳定,高度的工作时复杂的软件系统(例如,跨多领域广泛采用的编译器),多层单元测试和其他覆盖范围至关重要。

[还有许多其他特定于情境的因素,每个因素都起着重要作用。方式或其他方式,例如您的团队规模,预算,开发人员的才能,您首选的软件开发策略等。通常,在最高抽象层次上,我发现这两者之间的差异最大]

#12 楼

在我看来,产品/代码原型不需要测试,因为它们通常是使用与成品完全不同的过程和完全不同的目的交付的。

想象一下这种常见情况。您拥有某种以公司闻名的技术,您的销售团队或首席执行官会去找客户,并向他们出售可以利用您的技术的其他产品。他们在那里出售产品,然后向客户保证他们将在一个月内看到Beta版本。您什么都没有,甚至没有开发团队。

接下来发生的事情是,您根据同意/卖给客户的观点快速设计解决方案,组建了一个(通常是明星)工程师团队,并开始编写代码。当然,如果您的约会不拖延(他们总是这样做)并且您设法在三周而不是四周的时间内编写代码,那将是理想的选择。在这种情况下,您有一个额外的星期,如果您能够确保质量检查小组在本周的时间,您将对其进行测试。实际上,您没有多余的一周时间,并且/或者您的质量检查团队还需要另外两个月的时间来支持其他产品的交付。此外,您没有任何设计规格,因此质量检查团队不会知道他们应该测试什么。因此,您最终要通过一些自己的冒烟测试来交付编写的内容,而这并不是真正的测试,仅仅是因为您没有资格测试自己的代码。这里最大的因素是,客户端将很快看到一些承诺的功能。如果您的原型能够完成任务,那么您将回到绘图板,在此处设计并计划实际的1.0版-这次是正确的。

就单元测试而言,它们很好地维护了某些合同(我保证我的代码会这样做,如果没有的话,它会被破坏)。在进行原型制作时,您可能并不需要太在意合同,因为无论是因为客户端消失了,还是因为最终使用不同的技术/工具开发了1.0版,您的原型通常都无法成为1.0版。这里的一个例子是一个快速的原型网站,一个人用一个月的时间就用PHP很快地编写了一个快速的原型网站,然后您组成一个团队用JEE重写它。即使数据库也常常无法幸免于此更改。

评论


我已经看到太多“ protype”和“ temporary”代码投入生产,以至于不会。希望/计划重新实施是一回事。在时间表中找到时间是另一回事。

– jwernerny
2012年5月3日14:55

@jwernerny您是根据您的经验说的,我是我的。我认为这种说法适得其反。通常,出于商业原因,上市时间比质量重要得多。毫无疑问,这是一件可悲的事情,但这是生活中的事实。

–maksimov
2012年5月4日在9:09

#13 楼

当维护,扩展或传达应用程序逻辑而没有缺陷的逻辑理解能力超出(或将来可能超过)团队中知识最少的成员满足该理解能力时,您应该编写单元测试。 br />
基本上取决于您一次可以保持多少脑子。您可能会更加自信,可以编码(完全了解更改的影响),直到达到一定的复杂度为止。在此之前,单元测试会分散注意力,阻碍您前进。在团队中,阈值将更低,因此您非常需要立即进行单元测试来抵消小组的愚蠢。如果您从其他人那里接过一个未经测试的项目(或者您早就忘记了一个项目),则在更改任何内容之前,您都希望编写单元测试,因为您的理解将为零。

注意:编写更少的代码并练习YAGNI,可以降低复杂度,从而减少所需的单元测试数量。

评论


所以...您提倡只编写单元测试来帮助您学习/保护不熟悉的系统,否则就不进行单元测试?!也许我误会了你的答案。如果没有,那么这实际上不是单元测试的目的。特别是,如果您是TDD的拥护者,您将不胜感激,首先编写测试将指导您实现最少代码的工作,而重构则可以帮助您加强这些工作。因此,YAGNI最终成为您开发方法的核心宗旨和副产品。如果您的单元测试变得复杂,恕我直言,您可能做错了。

–S.Robins
2012年5月4日,9:37

我是说单元测试为理解应用程序之间的差距提供了桥梁。我确实说过,他们被要求“扩展”应用程序,因为有时候功能和功能的影响太难于一次跟踪所有内容,因此单元测试可以充当使之成为可能的框架。

–本尼迪克特
2012年5月9日13:56

是的,这是单元测试的另一种用途,但是肯定不是单元测试本身的特定目的。但是,我的评论是解决给出的答案,我认为这并不能令人满意地解决OP的问题。特别是,如果您认为单元测试会分散注意力,或者只需要它们来帮助知识最少的团队成员理解,那么您可能就不是很了解如何有效地应用单元测试,或者您可能觉得测试是一种最后一英里的任务。无论哪种方式,这都不是OP寻求其答案的方向。

–S.Robins
2012年5月15日下午6:28

就其价值而言,我确实同意您的看法,即在一个很难理解的应用程序中,单元测试可以让您分别测试思想和用例,而无需创建完整的应用程序。我个人使用单元测试API来帮助解决棘手的问题。但是,即使在看起来很琐碎的地方,我也会始终为我的代码编写单元测试,并且我首先进行此测试是为了获得测试的真正好处,即有信心随着时间的推移更改代码,而不必担心代码会被破坏并且以后需要进行广泛的独立测试。

–S.Robins
2012年5月15日下午6:33

在表达我的答案时,我试图提出一个简洁而全面的经验法则,以回答单元测试是否适合您的工作。因此,在这方面,直接对任择议定书问题作出回应。我还说过要编写测试,以解决复杂性“将来可能会超出”理解范围,以涵盖您建议的情况“现在看来很琐碎,但稍后……”。

–本尼迪克特
2012年5月15日上午11:38

#14 楼

单元测试固然很好,但在具有许多“活动部件”的复杂系统中,它们实际上并没有进行太多测试。

众所周知,单元测试可确保给定输入X为单元,则得到输出Y,其中X是所有适当的输入,而Y是所有适当的输出。但是,我发现大多数代码都能完成开发人员认为应该的工作。.但实际上却没有必要。
(您可能会认为它像枪一样。枪具有一堆精密零件,这些零件是分开制造的,然后组装。如果枪在实际射击时会爆炸,则是否对每个特定零件的功能进行了良好的测试都没关系。免责声明:我对火器武器一无所知(:)

在这种情况下,我们需要在模型生产环境中进行实际的系统测试。由于无论如何都在这里测试功能,因此单元测试的价值会有所降低。

但是,在这种情况下,单元测试仍然很有价值,因为它们可以确保功能实际上,您希望保持不变的确会保持不变,这非常有价值,因为它使您对需要进行重点测试的系统区域充满信心。

评论


对下票有什么解释吗?

–user606723
2012年5月3日18:59

请记住,我不喜欢你的答案,我只是不喜欢我的答案,所以我不认为你的答案有用,所以你必须学会​​不要把它当成个人。实际上,我不确定这如何回答实际问题。

– Mark Booth
2012年5月4日晚上8:50

@mark可悲的是,许多人的确使用投票来表示他们不喜欢所写的内容,或者他们个人认为答案(或部分答案)在他们看来是错误的,而且似乎常常没有给出答案。作者的好处是阅读完整的答案,可以使事物完全正确。

–S.Robins
2012年5月4日12:27

@ user606723不赞成投票的原因可能是OP在询问何时不适合创建单元测试,而您的答案首先是有效地指出单元测试在复杂的系统中测试不多-这是一个很大的概括,实际上可能是不正确的-最后,通过有效地说明单元测试是有价值的,因为单元测试可以保护系统免受功能更改的影响-这并不完全准确,也不适合发布的问题。

–S.Robins
2012年5月4日12:44

@ S.Robins-同意,偶尔提及选票的部分原因是提醒那些可能在投那些票的人,他们并不一定表示喜欢或不喜欢。

– Mark Booth
2012年5月4日13:23

#15 楼

IMO单元测试在任何代码库中都是不合适的(不是不必要的!),因为它需要大量的重构时间甚至需要彻底重写才能引入单元测试,因为在这段时间内分配给管理层非常困难。 。

#16 楼

在一个快速发展的小型组织中,我发现开发人员承受着巨大的压力以保持生产力和快速发展,以至于他们常常根本不愿意去测试自己的变更。

我们有一条总体政策规定:如果您进行更改(无论是错误修复还是增强功能),则开发人员应在提交代码进行进一步质量检查之前对其进行测试。

对于大多数实例,我们实际上并不编写单元测试因为我们的屏幕主要是通过以下方式设计的:如果在屏幕上进行了更改,则必须遍历其余逻辑,以便找出更改是否成功。

我发现开发人员必须进行自己的测试,无论是否进行了记录,因为他们最了解逻辑中的潜在弱点在哪里。

所以我想说,即使您没有为系统的每个小部分编写单元测试,也应该进行常识测试。