我正在将单元测试集成到我所工作的团队的开发过程中,对此有些怀疑。有什么好的方法可以使怀疑的开发人员相信团队中单元测试的价值?在我的特定情况下,我们将在添加功能或修复错误时添加单元测试。不幸的是,我们的代码库无法使其易于测试。
我正在将单元测试集成到我所工作的团队的开发过程中,对此有些怀疑。有什么好的方法可以使怀疑的开发人员相信团队中单元测试的价值?在我的特定情况下,我们将在添加功能或修复错误时添加单元测试。不幸的是,我们的代码库无法使其易于测试。
Answers:
每天我们办公室里都有这样的交流活动:
“伙计,我只是喜欢单元测试,我已经能够对某些工作方式进行大量更改,然后能够通过再次对它进行测试来确认我没有破坏任何东西……”
细节每天都在变化,但情绪却没有变化。单元测试和测试驱动的开发(TDD)具有许多隐藏的和个人的好处,以及显而易见的好处,您只是在他们自己做之前就无法真正向他人解释。
但是,忽略它,这是我的尝试!
单元测试使您可以快速更改代码。您知道它现在可以正常运行,因为您已经运行了测试,在进行需要进行的更改时,需要使测试重新运行。这样可以节省时间。
TDD可帮助您了解何时停止编码。通过测试,您可以确信自己已经做了足够的工作,并且可以停止调整并继续进行下一步。
测试和代码可以一起工作以获得更好的代码。您的代码可能是错误的/错误的。您的测试可能是错误/错误的。在TDD你指望的机会都被坏/越野车存在低。通常,这是需要修复的测试,但这仍然是一个很好的结果。
TDD帮助便秘编码。面对大量艰巨的工作,编写测试将使您快速前进。
单元测试可帮助您真正了解正在处理的代码的设计。您无需编写代码来执行某些操作,而是先概述要使代码遵循的所有条件以及从中获得的期望输出。
单元测试可为您提供即时的视觉反馈,我们都喜欢完成后所有这些绿灯的感觉。非常令人满意。中断后在哪里停下来也容易多了,因为您可以看到到达的地方–下一个需要修复的红灯。
与流行的信念单元测试相反,这并不意味着编写两倍的代码或编写速度较慢的代码。一旦掌握了它,它比没有测试的编码更快,更强大。测试代码本身通常是相对琐碎的,不会增加您的工作量。这是您只有在执行此操作时才会相信的方法:)
我认为正是福勒说:“经常运行的不完美测试比根本没有编写的完美测试要好得多”。我将其解释为允许我在我认为最有用的地方编写测试,即使我的其余代码覆盖范围很不完整。
好的单元测试可以帮助记录和定义应该做什么
单元测试有助于代码重用。将您的代码和测试都迁移到新项目。调整代码,直到测试再次运行。
我参与的许多工作都无法很好地进行单元测试(Web应用程序用户交互等),但是即使如此,我们在这家商店中都被测试感染,而当我们将测试捆绑在一起时,这是最快乐的。我不能高度推荐这种方法。
单元测试很像去体育馆。 您知道这对您有好处,所有论点都是有道理的,因此您开始锻炼。最初很急,这很不错,但是几天后,您开始怀疑这是否值得解决。您每天要花一个小时的时间去换衣服,骑仓鼠轮子,而且除了腿和胳膊酸痛以外,您不确定自己还能获得其他好处。
然后,大概一两个星期后,就在酸痛逐渐消失的时候,一个大限期开始了。您需要花每个醒来的时间来尝试完成“有用的”工作,因此您要切掉多余的内容,例如去健身房。您已经习惯了,到“大限期”结束时,您将回到第一位。如果您设法完全回到健身房,您会感到和第一次去时一样疼痛。
阅读一些内容,看看是否做错了。您开始会感到有些不合理的恶意,赞扬所有健康,快乐的人赞美运动的美德。您意识到自己没有太多共同点。他们不必开车15分钟即可去健身房。他们的大楼里有一个。他们不必与任何人争论运动的好处。这只是每个人都做并被接受为重要的事情。当“最后期限”临近时,他们不会被告知没有必要做运动,而老板会要求您停止进食。
因此,为了回答您的问题,单元测试通常值得您付出努力,但每个人所需的工作量并不会相同。 如果您要处理的公司中的意粉代码库实际上并不重视代码质量,那么单元测试可能需要大量的精力。(很多经理都会赞扬单元测试的赞美,但这并不意味着他们会坚持下去。)
如果您试图将单元测试引入您的工作中,而没有看到您期望得到的所有阳光和彩虹,请不要怪自己。您可能需要找到一份新工作才能真正使单元测试为您工作。
最好的说服方法...查找错误,为其编写单元测试,修复该错误。
该特定错误不太可能再次出现,您可以通过测试来证明。
如果您这样做足够,其他人将很快赶上。
thetalkingwalnut问:
有什么好的方法可以使怀疑的开发人员相信团队中单元测试的价值?
这里的每个人都会出于很多原因而突然想到单元测试良好的原因。但是,我发现,说服某人某事的最好方法通常是听取他们的论点并逐点解决。如果您倾听并帮助他们表达他们的疑虑,则可以解决每个问题,并可能将其转换为您的观点(或者至少让他们站稳脚跟)。谁知道?也许他们会说服您为什么单元测试不适合您的情况。不太可能,但可能。也许如果您发布他们反对单元测试的论点,我们可以帮助您确定反论点。
聆听和理解论证的两面很重要。如果您过于热心地采用单元测试而不考虑人们的担忧,那么您将陷入一场宗教战争(并且可能真的是毫无价值的单元测试)。如果您慢慢采用它,并从最低成本中获得最大收益的地方开始应用它,您也许能够证明单元测试的价值,并更有说服力。我意识到这并不像听起来那么容易-通常需要一些时间和谨慎的指标来提出令人信服的论点。
单元测试是一种工具,与其他工具一样,应该以这样的方式进行应用:收益(捕获bug)胜于成本(编写成本)。如果它们在没有意义的地方/地方,请勿使用它们,并记住它们只是您工具库中的一部分(例如检查,断言,代码分析器,形式化方法等)。我告诉开发人员的是:
如果他们有一个很好的论据,为什么没有必要(例如,太简单而不值得,或者太难了却不值得)以及如何以其他方式验证该方法(例如检查,断言),则可以跳过为该方法编写测试的过程,正式方法,互动/集成测试)。他们需要考虑到某些验证,例如检查和形式证明,是在某个时间点进行的,因此每次生产代码更改时都需要重复进行,而单元测试和断言可以用作回归测试(编写一次,然后重复执行) )。有时候我同意他们的观点,但是更多时候我会争论一种方法是真的太简单还是太难以进行单元测试。
如果开发人员认为某个方法似乎太简单而无法失败,那么花60秒为此写一个简单的5行单元测试是否值得?这5行代码将在下一年或以后的每天晚上运行(您每晚进行一次构建,对吗?),即使只是遇到一个可能花费了15分钟或更长时间才能发现的问题,也值得付出努力。和调试。此外,编写简单的单元测试会增加单元测试的数量,这使开发人员看起来不错。
另一方面,如果开发人员认为一种方法似乎很难进行单元测试(不值得进行大量工作),那么这可能很好地表明该方法需要进行分解或重构以测试易用的部件。通常,这些方法依赖于不寻常的资源(例如单例,当前时间)或外部资源(例如数据库结果集)。通常需要将这些方法重构为获取资源的方法(例如,调用getTime())和将资源作为参数的方法(例如,将时间戳作为参数)。我让他们跳过测试检索资源的方法,而是为现在将资源作为参数的方法编写单元测试。通常,这使编写单元测试更加简单,因此值得编写。
开发人员需要在单元测试的全面程度上划清界线。在开发的后期,每当我们发现错误时,他们都应确定是否进行更全面的单元测试可以解决问题。如果是这样,并且如果此类错误反复出现,则它们需要朝着将来编写更全面的单元测试的方向发展(从为当前错误添加或扩展单元测试开始)。他们需要找到适当的平衡。
重要的是要意识到单元测试不是万能的 是这样的事情太多了单元测试。在我的工作场所,每当我们吸取教训时,我都会不可避免地听到“我们需要编写更多的单元测试”。管理层点头表示同意,因为它被人们嘲笑为“单元测试” ==“好”。
但是,我们需要了解“更多单元测试”的影响。开发人员一个星期只能编写约N行代码,您需要确定该代码占单元测试代码与生产代码的比例。宽松的工作场所可能有10%的代码作为单元测试,而90%的代码作为生产代码,从而导致产品具有很多(尽管很容易出错)功能(例如MS Word)。另一方面,拥有90%的单元测试和10%的生产代码的严格车间将拥有功能很少的坚如磐石的产品(认为“ vi”)。您可能永远不会听到有关后一种产品崩溃的报告,但这可能与该产品的销量不佳以及与代码质量的影响不一样。
更糟糕的是,也许软件开发中的唯一确定性是“改变是不可避免的”。假设严格的车间(90%的单元测试/ 10%的生产代码)创建的产品正好具有2个功能(假设5%的生产代码== 1个功能)。如果客户出现并更改其中一项功能,则更改将浪费50%的代码(45%的单元测试和5%的生产代码)。宽松的工厂(10%的单元测试/ 90%的生产代码)的产品具有18个功能,但都无法很好地发挥作用。他们的客户完全改变了其4种功能的要求。即使更改是前者的4倍,也只会浪费掉一半的代码库(约25%=约4.4%单元测试+ 20%的生产代码)。
我的观点是,您必须传达自己的信息,即了解单元测试太少和太多之间的平衡-本质上,您已经考虑了问题的两个方面。如果您可以说服您的同龄人和/或您的管理层,那么您将获得信誉,并可能更有机会赢得他们。
我曾多次进行过单元测试,但我仍然坚信,鉴于我的情况,值得付出努力。
我开发网站,其中许多逻辑涉及创建,检索或更新数据库中的数据。当我试图“模拟”数据库以进行单元测试时,它变得非常混乱,似乎毫无意义。
当我围绕业务逻辑编写单元测试时,从长远来看,它并没有真正帮助我。因为我主要是独自从事项目工作,所以我倾向于直观地知道哪些代码区域可能受到我正在处理的内容的影响,因此我手动测试了这些区域。我想尽快为客户提供解决方案,而单元测试通常看起来很浪费时间。我列出了手动测试,并亲自完成了这些测试,并在进行过程中将其选中。
我可以看到,当一个开发人员团队从事一个项目并更新彼此的代码时,这可能是有益的,但是即使如此,我仍然认为,如果开发人员的素质很高,那么良好的沟通和良好的编写代码通常就足够了。 。
[我要指出的是,我在上面看不到]
“每个单元测试,他们不一定都意识到这一点-事实”
考虑一下,您编写了一个函数来解析字符串并删除换行符。作为新手开发人员,您可以通过在Main()中实现它来从命令行运行一些案例,也可以通过按钮将视觉前端组合在一起,将函数绑定到几个文本框和一个按钮,然后查看怎么了。
那就是单元测试-基本的和糟糕的组合在一起,但是您只在少数情况下测试代码。
您写的东西更复杂。当您通过一些案例(单元测试)并调试代码并进行跟踪时,它将引发错误。您在浏览过程中会查看值,并确定它们是对还是错。这是某种程度上的单元测试。
这里的单元测试实际上就是采取这种行为,将其形式化为结构化模式并保存下来,以便您可以轻松地重新运行这些测试。如果您编写一个“适当的”单元测试用例而不是手动测试,那么它所花费的时间是相同的,或者可能比您所经历的要少,并且可以重复一次
多年以来,我一直试图说服人们他们需要为其代码编写单元测试。无论他们是先编写测试(如在TDD中),还是在编写功能代码之后,我总是试图向他们解释为代码进行单元测试的所有好处。几乎没有人不同意我。您不能不同意显而易见的事情,任何聪明的人都会看到单元测试和TDD的好处。
单元测试的问题在于,它需要改变行为,并且很难改变人们的行为。用言语,您会得到很多人的同意,但是您做事的方式不会看到很多变化。
您必须通过说服人们。您个人的成功将吸引更多的人,而不是您可能拥有的所有论点。如果他们看到您不仅在谈论单元测试或TDD,而且您正在做自己的演讲,并且您成功了,那么人们会尝试模仿您。
您还应该担任领导角色,因为没有人第一次正确编写单元测试,因此您可能需要指导他们如何进行单元测试,向他们展示方法以及可供他们使用的工具。在他们编写第一个测试时帮助他们,回顾他们自己编写的测试,并向他们展示您从自己的经验中学到的技巧,习语和模式。一段时间后,他们将开始自己看到收益,并且他们将改变其行为,以将单元测试或TDD纳入其工具箱。
改变不会在一夜之间发生,但是只要有一点耐心,您就可以实现自己的目标。
关于单元测试的最好的事情之一就是您的代码将变得更容易测试。在没有测试的情况下创建的预先存在的代码始终是一个挑战,因为由于它们并不是要进行单元测试的,因此在类之间,类中难以配置的对象之间进行高级别的耦合并不是罕见的,例如电子邮件发送服务参考-等等。但是,不要让这让您失望!您会发现,随着开始编写单元测试,您的总体代码设计会变得更好,并且测试越多,您就越有信心对其进行更多更改,而不必担心会破坏您的应用程序或引入错误。 。
进行单元测试代码的原因有很多,但是随着时间的推移,您会发现节省测试时间是最好的理由之一。在我刚刚交付的系统中,尽管声称与手动测试系统相比,我花费更多的时间进行测试,但我仍坚持进行自动化的单元测试。完成所有单元测试后,我在不到10分钟的时间内运行了400多个测试用例,每次必须对代码进行小改动时,我所要做的全部工作是确保代码仍能正常工作而没有错误,只有十个分钟。您能想象一个人花时间手动运行这400多个测试用例吗?
当涉及到自动化测试(无论是单元测试还是验收测试)时,每个人都认为浪费精力来编写您可以手动执行的操作,有时候这是对的-如果您计划只运行一次测试。自动化测试最好的部分是您可以毫不费力地运行它们几次,并且在第二次或第三次运行之后,您已经浪费了时间和精力。
当涉及重构或重写一段代码时,单元测试也特别有用。如果您具有良好的单元测试覆盖范围,则可以放心地进行重构。没有单元测试,通常很难确保您没有破坏任何东西。
简而言之-是的。在某种程度上,它们值得每一刻的努力。最终,测试仍然是代码,并且就像典型的代码增长一样,最终将需要重构测试以保持可维护性和可持续性。一吨的GOTCHAS!当涉及到单元测试时,但是,天哪,没什么,我的意思是,NOTHING比一组丰富的单元测试更能使开发人员更自信地进行更改。
我现在正在开发一个项目...。有点TDD,并且我们将大多数业务规则封装为测试...我们现在大约有500个左右的单元测试。在过去的迭代中,我不得不修改数据源以及桌面应用程序与该数据源的接口。花了我几天的时间,整个过程中我一直在运行单元测试,以查看发生了什么问题并进行修复。做出改变; 建立并运行测试;修理你弄坏的东西。洗涤,漂洗,根据需要重复。传统上需要几天的质量检查和大量的压力,这是一次短暂而愉快的经历。
预先做好准备,需要付出一些额外的努力,而当您不得不开始关注核心功能时,它需要支付10倍的费用。
我买了这本书-这是有关xUnit Testing的圣经-可能是我书架上参考最多的书之一,并且我每天都在浏览它: 链接文本
单元测试绝对值得付出努力。不幸的是,您选择了一个困难的(但不幸的是很常见)的方案来实现它。
从单元测试中获得的最大好处是从头开始使用它-在一些精选的小型项目中,我很幸运在实现类之前就编写了单元测试(接口已经完成了)点)。通过适当的单元测试,您可以在班级中仍处于初级阶段的错误中发现并修复错误,而这些错误无疑会在将来毫无疑问地集成到复杂的系统中。
如果您的软件是面向对象的,那么您应该能够在类级别上添加单元测试,而无需花费太多精力。如果不是那么幸运,那么您仍应尽可能尝试合并单元测试。确保在添加新功能时,使用清晰的界面就可以很好地定义新部件,并且会发现单元测试使您的工作变得更加轻松。
当您说“我们的代码库无法使其易于测试”时,这是代码气味的第一个迹象。编写单元测试意味着您通常以不同的方式编写代码,以使代码更具可测试性。在我看来,这是一件好事,因为多年来我在编写必须为其编写测试的代码时所见,这迫使我提出更好的设计。
我不知道。很多地方不做单元测试,但是代码的质量很好。微软进行单元测试,但是比尔·盖茨在演讲中给出了蓝屏。
我写了一篇有关该主题的大型博客文章。我发现单靠单元测试是不值得的,通常会在截止日期临近时被削减。
与其从“测试后”验证的角度谈论单元测试,不如着眼于在实施之前编写规范/测试/想法时发现的真实值。
这个简单的想法改变了我编写软件的方式,并且我不会回到“旧”方式。
是的-单元测试绝对值得付出努力,但您应该知道这不是万灵丹。单元测试是可行的,您将不得不努力保持测试的更新和相关性,因为代码会发生变化,但是所提供的价值值得您付出一定的努力。不受惩罚的重构能力是一项巨大的好处,因为您可以始终验证功能在任何更改代码之后运行测试。诀窍是不要过于迷恋要测试的工作单元或脚手架测试需求的方式,以及何时单元测试确实是功能测试等。人们会争论数小时。最后,现实是,在编写代码时进行的任何测试总比不进行测试要好。另一个公理是质量而不是数量-我见过1000'的代码库 测试基本上没有意义,因为其余测试实际上并没有测试任何有用的东西或特定领域的任何特定领域,例如业务规则等。我也看到过代码库覆盖了30%的代码,但是这些测试是相关的,有意义的,并且确实很棒,因为它们测试了所编写代码的核心功能并表达了应如何使用该代码。
在探索新框架或代码库时,我最喜欢的技巧之一是为“ it”编写单元测试以发现事物的工作方式。这是一种学习更多新知识的好方法,而不是阅读干燥的文档:)
最近,我在工作场所经历了完全相同的经历,发现他们中的大多数人都知道理论上的好处,但是必须将这些好处专门卖给他们,所以这是我(成功地)使用的要点:
还有那个大...
单元测试对大于任何开发人员所能承受的项目有很大帮助。它们使您可以在签入之前运行单元测试套件,并发现是否损坏了某些内容。这减少了很多事情,不必坐下来不停地旋转手指,而又等待其他人修复他们签入的错误,或者麻烦恢复他们的更改,以便您可以完成一些工作。它在重构中也非常有价值,因此您可以确保重构后的代码能够通过原始代码所做的所有测试。
我同意与大多数人相反的观点: 不用编写单元测试 是可以的,尤其是繁重的原型编程(例如AI)很难与单元测试结合。