我认为我的项目已经解耦到足以进行单元测试的程度。但是,就笔迹和功能而言,我的项目到底需要多大才能使单元测试值得?

我们都会犯错误,没有人能做到完美,但是我认为自己是一个体面的程序员,可以逐步解决小项目的错误。还是无论项目大小如何,都必须进行单元测试?

评论

您所做的一个大不正确的假设是,该项目仅适合您,并且仅目前。如果您将其放置几个月,又做其他事情,然后又回到原来的状态,该怎么办?您是否对成为“体面的程序员”有同样的信心(与是否测试无关)?如果其他人接管您的项目怎么办...?一个伟大的博客作者(很难再活动了)写道,您应该始终“迎合代码读取器,而不是代码编写器”。

怎么样(对于C#.NET意味着):int x = 3 *(1/3);操作完成后,x中存储的值是多少?我的意思是,甚至一个行代码都可能需要测试,因为它可能会导致错误,或者是因为您不知道,或者是因为您知道但做错了代码。

@aaamos,我想你错过了我的意思。仅问这个问题的事实表明,我也考虑满足代码读取器的需求。

两种方法都做完了,我可以告诉您,编写程序时(即项目很小时)编写测试要容易得多,而回过头再编写项目测试时,您会感觉到项目遇到了一些随意性,这要容易得多。我们应该立即编写测试”条件。

您问错了问题。项目多大无关紧要。问题是,您是否在乎它是否正确?如果正确性很重要,那么单元测试是提高正确性的有效方法。

#1 楼

您的项目已经足够大。
根据我的经验,一类和一个功能足以考虑进行单元测试的需要。
    class Simple {
        boolean reallySimple() {
            return true; // how do we make sure it doesn't change to false?
        }
    }
    
    
    class SimpleTest {
        void assertReallySimple() {
            // ensure reallySimple return value isn't changed unexpectedly
            UnitTestFramework.assertTrue(new Simple().reallySimple());
        }
    }


评论


当然,您应该从0 class / 0功能点开始……如果您遵循TDD :)

–卡兹龙
2012年8月8日12:52

+1。如果您的程序足够大,可以有错误,那么它足够大,可以进行单元测试。

–詹森·奥伦多夫(Jason Orendorff)
2012年8月8日14:03

@JasonOrendorff:我正在将其模拟成海报,并将其放在我的办公室中。辉煌。

–贾斯汀·ᚅᚔᚈᚄᚒᚔ
2012年8月8日14:50

另外,它允许“安全”重构。

– Timo
2012年8月8日15:43

尽管我不一定不同意这种观点,但是如果您的代码确实如此简单,那么您可能只需要断言而不是进行全面的单元测试即可。

– Chuu
2012年8月8日在21:26



#2 楼

我从来没有接受过“必须对所有内容进行单元测试”的想法,尽管肯定有一些人(请参阅gnat的答案!)。

就我而言,主要单元测试的好处是:


帮助确保更改不会破坏事物。
帮助您设计类的明智接口(因为它迫使您成为您的客户端)自己的代码)。
帮助记录如何使用您的代码。

基本上,您需要权衡这些因素来编写和维护测试所花费的时间。

数字1通常足以使其值得编写测试。以我的经验,> 95%的代码迟早都会被修改。

评论


同意这一点-在一家开发人员商店工作时,您需要在软件质量和测试所有内容之间取得平衡(这会占用您很多时间)。不要忘记,每次进行更改时,可能都需要修改单元测试以适合

–马特·威尔科(Matt Wilko)
2012年8月8日上午10:53

您不应该测试所有内容,但是应该测试暴露给外界的任何行为。测试肯定有维护成本,正如肯特·贝克(Kent Beck)在某个SO答案中所说(我认为是SO)-测试足以使您确信代码正确。

–Wayne Werner
2012年8月8日在11:44

我还要补充一点,如果您仅进行最少的自动化测试,则单元测试的目标级别是错误的。取而代之的是进行高级集成/烟雾测试,这些测试可以将端对端地推送一些数据集,而不会模拟任何内容。您希望这些测试尽可能多地利用您的代码库,并涵盖所有正常的用例和执行路径。知道您的更改在应用程序中某处发生故障的几率是75%,比知道您破坏SomeClass.OneOfTheHandfulOfTestedFunctions()的几率要大得多。

–丹爱抚着火光
2012年8月8日12:30

嗯,我想您错过了一个:“确保代码按预期的方式运行!”

– BlueRaja-Danny Pflughoeft
2012年8月8日在16:40

@ BlueRaja-DannyPflughoeft:实际上,更准确地说:“确保代码通过您编写的单元测试!”

–vaughandroid
2012年8月9日15:53

#3 楼

很简单:如果您在运行一次该程序后就将其丢弃,则不需要进行单元测试。如果某个大小低于该大小,而单元测试不付钱,则您必须牢记:“我是否达到了不可思议的大小?我应该开始编写测试吗?”现在,众所周知,程序员在预测未来方面很糟糕,并且在判断自己的技能方面也非常糟糕。现在,即使等待一个月,对您来说仍然清晰的代码将变得难以理解。您绝对肯定的项目将永远不会再被使用,并且您只会在很少的机会上徘徊,您可能希望先查找自己如何解决问题,然后再次提出请求,并将收到变更请求。

因此,很可能您会误认为测试是否有用,并且当您开始需要测试时,您已经100%不确定要测试的确切语义是什么。由于我认为除琐碎的一次性程序外,所有其他程序都可以从单元测试中受益,因此,我认为,对那些无法再运行的测试进行扩展所付出的成本对于扩展未测试和无法理解的代码的风险可以忽略不计。

评论


众所周知,程序员在判断自己的预测未来技能方面表现不佳

–superM
2012年8月8日在8:53

@superM我同意你的看法。在我短暂的职业生涯中,我曾经写过的“运行一次然后扔掉”程序全部搁置了,每隔几天运行一次,并且变得对业务至关重要。我称“临时”又称临时永久性效果。

–贾琳
2012年8月8日,11:20

@Jalayn难道不是简单的答案就是一旦意识到这一点就应该回去并添加单元测试吗?

– Cornel Masson
15年3月25日在8:45

@CornelMasson你是完全正确的,因为缺少测试,通常很难说服经理“还没有完成”:

–贾琳
15年3月25日在12:21

@Jalayn:太正确了!

– Cornel Masson
15年3月25日在13:27

#4 楼

前段时间我找到了一篇不错的文章:为什么单元测试可以加快开发速度。
它可以帮助您回答问题。


...如果代码库...提供了大量的单元测试。一组会说:“如果所有测试都成功,则我保证代码仍会执行应做的事情”;如果测试失败,它将准确地向您显示某些行为被破坏了。太好了,我可以更改代码以添加我想要的内容,而无需徘徊,如果代码仍然可以执行其应做的事情,那么我只需运行...测试即可,并且有信心。作为软件工程师,这是一个伟大的世界。我注意到我可以更快地前进...

我有信心。

这可能是单元测试在企业环境中加速开发的最重要原因。 。

我可以相信,如果所有测试通过,一切仍然可以进行。如果测试失败,他们将指出问题的根源。

...您必须具有较高的单元测试覆盖率和良好的单元测试。在遵守这些条件的情况下,您会发现自己的处境是添加新功能的工作几乎与应用程序的大小无关,并且从长远来看,它将加速开发。


迈克尔·费瑟斯(Michael Feathers)在他的书中介绍了两种处理代码更改的方法:


编辑和祈祷,
发现和修改。

代码库有多大都没关系。

#5 楼

根据肯特·贝克(Kent Beck)在回答“堆栈溢出”问题时所说的,您的单元测试有多深?应该测试可能会出错的代码。一种错误(例如在构造函数中设置错误的变量),我不对其进行测试。


评论


好点,这意味着OP的问题是错误的;是否进行测试与项目的规模无关。 5行代码库可能需要测试,而大型代码库中的1行方法可能不需要测试(尽管该代码库中的其他内容也需要这样做)。

–内森·朗(Nathan Long)
2012年8月8日在16:36

这可能适用于您一个人从事的小型项目,但是对于一个已经完成的项目(您无法控制将来的工作人员)或任何开源的项目,您都需要测试一切。而且您需要立即开始,因为稍后它将“太难以回填所有已编写的代码”

–xaxxon
13年1月12日在17:53

@xaxxon:肯特实际上是在与曼苏罗联系的相同答案中谈论这一点的,他说:“在为团队编写代码时,我修改了策略以仔细测试我们共同容易出错的代码。”

– henko
13年1月12日在19:47

不,那仍然是短视。您不知道将来将由谁来负责该代码。这是困扰初级开发人员的心态类型。

–xaxxon
13年1月13日在3:21

#6 楼

实施单元测试可以节省时间并改进:


错误跟踪
重构和/或重写代码
集成测试
回归测试等。

必须为程序的相对复杂的部分编写单元测试。

如果确定现在编写单元测试不会节省您的时间,则可以跳过它。但是,您永远不会知道,就我个人而言,我不认为不编写单元测试而是手动进行所有测试会更便宜(在时间,金钱和神经方面)的情况。

评论


通常是一个很好的答案,所以+1。但是,我认为您的最后一点错过了您仍然需要/需要手动测试单元测试的事实!

–vaughandroid
2012年8月8日在9:16

@Baqueta,也许我听不清楚,但是我并不是说说单元测试完全取代了手动测试

–superM
2012年8月8日在9:31

#7 楼

观察到回归的发生或恐惧会导致编辑中的某些内容而不引起注意,请立即进行测试。

将这种恐惧点燃,让它增长到足够的大小:测试越早越好。

请注意:取决于您在项目中的角色,单元测试可能不是您要编写的唯一测试。

每个人都理所当然地痴迷于单元测试,因为它不好过去的主流测试实践;但是,如果您以前从未进行过测试,那么您真的应该专注于一般的测试,仅凭单元测试就无法解决世界上的问题。

评论


我明白您的意思,但是还没有对初学者进行基本测试。您还可以详细说明“一般测试”的含义。谢谢。

– Lamin Sanneh
2012年8月8日在8:27

至少还有两种其他类型的测试-集成测试和验收测试。单元测试涵盖一个特定的单元(例如,该类的此功能应该可以使Fizz the Fizz)。您可以模拟/存根该类与之交互的所有其他地方,并将其传递给fake-o数据。进行集成测试时,您将两个(或多个)类组合在一起以确保您的类按照您认为的方式组合在一起。最终,您建立了足够的测试,正在对整个系统进行端到端测试,有时也称为“烟雾测试”。

–Wayne Werner
2012年8月8日19:33

也有回归测试兜售法庭。回归测试通常比单元测试大,可能要花一天的时间才能完成,可能意味着需要访问测试数据和特殊的测试环境。实际上,单元测试是更小,更时尚,更易于维护的(旧式)回归测试版本。

– ZJR
2012年8月9日在0:47



#8 楼

通常,可以通过回答以下问题来回答“我应该对此进行单元测试”:“该功能正常工作是否重要,并且知道何时停止工作对我来说是否重要?”当然,这要复杂得多,但这是一个很好的起点。最终,您还将权衡代码是否已经通过在另一个函数中使用而进行了测试,或者您的时间是否会花费在另一个函数上等,等等。

#9 楼

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

进行单元测试与不进行单元测试的区别在于编写测试的成本之间的区别并且将其运行成本与手工测试成本进行比较。

如果编写单元测试的成本为2分钟,而运行单元测试的成本实际上为0,但是手动测试代码需要1分钟,然后如果两次运行测试,您甚至会收支平衡。我的代码进行单元测试。当我确实编写测试时,它们是肿的,沉重的东西,这仅鼓励我认为我应该只在知道需要它们时才编写单元测试。

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

根据我的经验,通过考虑测试进行开发,您最终会获得更简洁的界面,更集中的类和模块和通常更多的SOLID,可测试代码。该代码已经进行了单元测试”。每次我不得不尝试向具有高耦合性的代码添加单元测试功能时,我一直在想:“如果以非耦合的方式编写代码,这将变得更加容易”。 /> TL; DR版本:

编写测试的时间以及编写测试所需的次数,可能比编写手动测试的成本要少它可以根据需要进行多次。

请记住,尽管使用TDD,但随着测试水平的提高,编写测试的成本可能会降低,并且除非代码绝对琐碎,否则最终运行测试的频率可能会超出预期。

#10 楼

我认为,决定项目是否应使用测试的不是项目的大小,而是项目的类型。

如果您正在进行概念验证,或者在其他项目中目标是从编码中学习,然后不需要测试。如果要使用该项目,甚至可以将其投入生产,就应该对其进行测试。

罗伯特·C·马丁(Robert C. Martin)的“清洁代码”的一句话:“如果编写很简单,那么它就很简单了。测试”,因此没有任何借口可以跳过简短程序的测试。

#11 楼

实际上,这与大小无关,它是您要使用的功能(以及它的年龄)。如果我想学习一项技术的工作原理并计划将其扔掉(我们称这是Scrum的峰值),那么我将无需进行大量测试就可以编写代码。如果您打算进一步开发它(即使只是闲逛),则应该围绕代码编写测试。 TDD在测试技术之前就已经是一种设计技术。在确定执行细节之前,您希望清楚了解代码要执行的操作。我也不建议尝试围绕大量的遗留代码编写大量的单元测试。尝试识别那些复杂的部分(具有很高的圈复杂度/意大利面条式的感觉)和那些经常失败的部分(它们通常是相同的)。
正如其他人所建议的那样,我会去阅读肯特·贝克(Kent Beck)关于TDD的书,并且一定会读迈克尔·费瑟(Michael Feather)的书。他们没有涉及的太多是围绕代码编写单元测试的政治方面。许多开发人员讨厌不得不更改其代码以使其可测试,并且许多开发人员根本不认为需要测试代码。这是我们必须从事的工作。其他所有工程学科都必须证明(通常是数学上)他们的工作符合规范。我们应该做同样的事情。

#12 楼

在类或功能的限制中绑定项目,然后判断是否适合单元测试可能是错误的。对应用程序进行单元测试有很多好处,但是当您必须维护应用程序或必须在分布式环境中工作时,真正的美就开始了。所以选择来了。即使您的代码进行很小的更改也会造成灾难。

我不仅会建议“单元测试”,而且还会建议检查您的代码覆盖率,以确保单元测试覆盖了最大的代码范围。代码覆盖率的阈值不得小于95%,目标值必须在100%左右。您可以使用工具来跟踪代码覆盖范围并生成报告。
Visual Studio提供覆盖率数据-http://msdn.microsoft.com/zh-cn/library/ms182496(v=vs.80).aspx
也可以使用NCover或dotCover。
/>