我正在努力将单元测试集成到我工作的团队的开发过程中,并且有一些怀疑论者。有什么好的方法可以让团队中持怀疑态度的开发人员相信单元测试的价值?在我的具体情况下,我们将添加单元测试,因为我们添加功能或修复了错误。不幸的是,我们的代码库不适合简单的测试。
答案 0 :(得分:722)
我们办公室的每一天都有一个类似的交流:
“男人,我只是喜欢单元测试,我刚刚能够对某些工作方式做出一些改变,然后能够通过再次运行测试来确认我没有破坏任何东西。 ..“
细节每天都在变化,但情绪却没有。单元测试和测试驱动开发(TDD)有很多隐藏的和个人的好处,以及你自己无法真正解释的明显的好处,直到他们自己做。
但是,忽略这一点,这是我的尝试!
单元测试允许您快速对代码进行重大更改。你知道它现在有效,因为你已经运行了测试,当你需要进行更改时,你需要让测试再次运行。这节省了数小时。
TDD可帮助您了解何时停止编码。你的测试让你相信你已经做了足够的事情,可以停止调整并继续下一步。
测试和代码协同工作以实现更好的代码。你的代码可能很糟糕/错误。你的测试可能很糟糕/错误。在TDD中,你很想看两者糟糕/错误的可能性很低。通常这是需要修复的测试,但这仍然是一个好结果。
TDD有助于编码便秘。如果面对大量艰巨的工作,写下测试将让你快速行动。
单元测试可帮助您真正了解正在使用的代码的设计。您不是编写代码来执行某些操作,而是首先概述您要对代码进行处理的所有条件以及您希望从中获得的输出。
单元测试为您提供即时视觉反馈,我们都喜欢当我们完成时所有绿灯的感觉。这非常令人满意。在中断之后离开的位置也更容易,因为你可以看到你需要去的地方 - 下一个需要修理的红灯。
与流行的观点相反,单元测试并不意味着编写两倍的代码,或编码速度较慢。一旦你掌握了它,它比没有测试的编码更快,更强大。测试代码本身通常是相对微不足道的,并不会给你正在做的事情增加很大的开销。这是你只会在做的时候才会相信的:)
我认为Fowler说:“不完美的测试,经常运行,比完全没有写过的完美测试要好得多”。我将此解释为允许我编写测试,即使我的其余代码覆盖率严重不完整,我认为它们也是最有用的。
良好的单元测试可以帮助记录和定义应该做的事情
单元测试有助于代码重用。将您的代码和迁移到新项目中。调整代码,直到测试再次运行。
我参与的大量工作并不能很好地进行单元测试(网络应用程序用户交互等),但即便如此,我们都在本店测试感染,并且当我们的测试被绑定时最开心下。我不能高度推荐这种方法。
答案 1 :(得分:421)
单位测试很像去健身房。你知道这对你有好处,所有的论据都有意义,所以你开始锻炼了。这是一个很好的初期热潮,但几天后你开始怀疑它是否值得这么麻烦。你需要一个小时的时间来换衣服,然后在仓鼠轮上跑步,你不确定除了腿部和手臂疼痛之外你还得不到其他任何东西。
然后,在一两周之后,就像疼痛消失一样,一个大截止日期即将开始。你需要花费每个醒着的时间来完成“有用”的工作,这样你就可以减少无关紧要的东西,比如去健身房。你没有这个习惯,当大截止日期结束时,你又回到原点。如果你设法让它回到健身房,你会感觉像第一次去的那样疼痛。
你做一些阅读,看看你做错了什么。你开始感到一点点非理性的厌恶,所有的健康,快乐的人颂扬运动的美德。你意识到你并没有很多共同之处。他们不需要开15分钟就可以去健身房;他们的建筑物中有一个。他们不必与任何人争论运动的好处;这只是每个人所做的事情并且接受同样重要的事情。当一个大截止日期临近时,他们不会被告知锻炼是不必要的,而不是你的老板要求你停止进食。
所以,为了回答你的问题,单元测试通常是值得的,但是所需的工作量并不是每个人都相同。单元测试可能需要大量的如果您在一家公司没有实际重视代码质量的情况下处理意大利面条代码库,那就付出了努力。 (许多管理人员会赞扬单元测试的赞誉,但这并不意味着他们会在重要时坚持下去。)
如果您正在尝试将单元测试引入您的工作中,并且没有看到您所期望的所有阳光和彩虹,请不要责怪自己。您可能需要找到一份新工作才能真正让Unit Testing为您服务。
答案 2 :(得分:136)
最好的说服方法......找到一个bug,为它编写一个单元测试,修复bug。
这个特定的错误不太可能再次出现,你可以用你的测试证明它。
如果你这么做,其他人就会很快流行起来。
答案 3 :(得分:69)
答案 4 :(得分:38)
我已多次玩过单元测试,但我仍然相信,鉴于我的情况,这是值得的。
我开发网站,其中大部分逻辑涉及创建,检索或更新数据库中的数据。当我试图“模拟”数据库进行单元测试时,它已经非常混乱,似乎有点无意义。
当我编写关于业务逻辑的单元测试时,从长远来看它从来没有真正帮助过我。因为我主要在项目上工作,所以我倾向于直观地知道哪些代码区域可能会受到我正在处理的事情的影响,我会手动测试这些区域。我想尽快为我的客户提供解决方案,单元测试通常似乎是浪费时间。我列出了手动测试并自己走过去,在我走的时候勾选它们。
我可以看到,当一个开发团队正在开发项目并更新彼此的代码时,这可能是有益的,但即便如此,我认为如果开发人员具有高质量,良好的沟通和编写良好的代码应该经常就够了。
答案 5 :(得分:31)
单元测试的一个好处是它们可以作为代码行为方式的文档。好的测试有点像参考实现,队友可以查看它们以了解如何将代码与您的代码集成。
答案 6 :(得分:26)
单元测试非常值得初始投资。自从几年前开始使用单元测试以来,我发现了一些真正的好处:
代码段可以帮助您减少创建测试的开销。创建能够在几秒钟内创建类轮廓和相关单元测试夹具的片段并不困难。
答案 7 :(得分:25)
你应该尽可能少地测试!
意思是,你应该编写足够的单元测试来揭示意图。这经常被掩盖。单元测试会花费你。如果您进行更改并且必须更改测试,则不太灵活。保持单元测试简短而甜蜜。然后他们有很多价值。
我经常看到许多测试永远不会破坏,大而笨拙并且没有提供很多价值,它们最终会减慢你的速度。
答案 8 :(得分:23)
我没有在其他任何答案中看到这一点,但我注意到的一件事是我可以更快地调试。您不需要通过正确的步骤深入了解您的应用程序以获取您修复的代码,只是发现您发生了布尔错误并需要再次执行此操作。通过单元测试,您可以直接进入正在调试的代码。
答案 9 :(得分:21)
[我有必要让我无法看到上面的内容]
“每个人单位测试,他们不一定意识到 - 事实”
考虑一下,你编写一个函数来解析一个字符串并删除换行符。作为一个新手开发人员,您可以通过在Main()中实现它来从命令行运行一些案例,或者将视觉前端与按钮组合在一起,将您的函数绑定到几个文本框和一个按钮,然后查看会发生什么。
这是单元测试 - 基本和非常合在一起,但你测试了一些代码片段。
你写的东西更复杂。当您抛出一些案例(单元测试)并调试代码并进行跟踪时,它会抛出错误。你在经历时会看到价值观,并决定它们是对还是错。这在某种程度上是单元测试。
这里的单元测试确实采取了这种行为,将其形式化为结构化模式并保存,以便您可以轻松地重新运行这些测试。如果你编写一个“正确的”单元测试用例而不是手动测试,它会花费相同的时间,或者当你经验丰富时可能会更少,并且你可以一次又一次地重复它
答案 10 :(得分:16)
多年来,我试图说服人们他们需要为他们的代码编写单元测试。无论他们是首先编写测试(如在TDD中)还是在编写功能之后,我总是试图向他们解释为代码进行单元测试的所有好处。几乎没有人不同意我的观点。你不能不同意明显的事情,任何聪明的人都会看到单元测试和TDD的好处。
单元测试的问题在于它需要行为改变,而且很难改变人们的行为。用言语,你会得到很多人同意你,但你不会看到他们做事的方式有很多变化。
你必须通过这样做来说服人们。你的个人成功将吸引更多的人,而不是你可能拥有的所有论点。如果他们发现你不只是在谈论单元测试或TDD,而是你正在做你所宣讲的,并且你成功了,人们会试着模仿你。
你也应该担任主角,因为没有人在第一时间正确地编写单元测试,所以你可能需要指导他们如何做,向他们展示方式,以及他们可用的工具。在他们编写第一次测试时帮助他们,查看他们自己编写的测试,并向他们展示您通过自己的经历学到的技巧,习语和模式。过了一会儿,他们会开始自己看到好处,他们会改变行为,将单元测试或TDD纳入他们的工具箱。
改变不会在一夜之间发生,但只要有一点耐心,你就可以实现目标。
答案 11 :(得分:12)
经常被掩盖的测试驱动开发的一个主要部分是编写可测试代码。它起初似乎是一种妥协,但你会发现可测试的代码最终也是模块化的,可维护的和可读的。 如果你仍然需要帮助说服人this是关于单元测试的优点的简单介绍。
答案 12 :(得分:11)
如果您现有的代码库不适合单元测试,而且它已经在生产中,那么通过尝试重构所有代码以使其可以进行单元测试,您可能会产生比解决更多的问题。
您可能最好还是努力改进集成测试。有很多代码在没有单元测试的情况下编写起来更简单,如果QA可以根据需求文档验证功能,那么就完成了。运送它。
在我看来,这个经典的例子是嵌入在链接到GridView的ASPX页面中的SqlDataReader。代码全部在ASPX文件中。 SQL位于存储过程中。你有什么单元测试?如果页面做了它应该做的事情,你真的应该把它重新设计成几层,这样你就可以自动化吗?
答案 13 :(得分:10)
单元测试最好的一点是,您的代码将变得更容易测试。在没有测试的情况下创建的预先存在的代码总是一个挑战,因为它们不是单元测试的,所以在类之间具有高级别的耦合,在类中难以配置的对象(如电子邮件)并不罕见发送服务参考 - 依此类推。但是不要让这让你失望!当你开始编写单元测试时,你会发现你的整体代码设计会变得更好,你测试得越多,你就越有信心对它进行更多的更改,而不用担心会破坏应用程序或引入bug
对您的代码进行单元测试有几个原因,但随着时间的推移,您会发现节省测试的时间是执行此操作的最佳理由之一。在我刚刚交付的系统中,尽管声称我花费更多时间进行测试而不是手动测试系统,但我坚持进行自动化单元测试。完成所有的单元测试后,我在不到10分钟的时间内运行了400多个测试用例,每次我不得不对代码进行一些小的更改,我只需要确保代码仍在工作,没有错误就是十分钟。你能想象一下手动运行400多个测试用例的时间吗?
当涉及到自动化测试时 - 无论是单元测试还是验收测试 - 每个人都认为,如果您计划仅运行一次测试,那么您可以手动编写可以执行的操作,而且有时这是真的。自动化测试的最佳部分是您可以毫不费力地多次运行它们,并且在第二次或第三次运行之后,您已经浪费了浪费的时间和精力
。答案 14 :(得分:8)
单元测试在重构或重写代码时也特别有用。如果你有良好的单元测试覆盖率,你可以放心地重构。没有单元测试,通常很难确保你没有破坏任何东西。
答案 15 :(得分:7)
我是一名维护工程师,负责记录糟糕,糟糕和庞大的代码库。我希望编写代码的人为它编写了单元测试
每次我做出更改并更新生产代码时,我都害怕因为没有考虑某些条件而引入错误。
如果他们写了测试,那么对代码库的更改会更容易,更快。(同时代码库会处于更好的状态)..
我认为单元测试在编写api或框架时非常有用,这些api或框架必须持续多年,并且由原始编码器以外的人使用/修改/演化。
答案 16 :(得分:7)
总之 - 是的。他们值得每一分努力......到了一定程度。在一天结束时,测试仍然是代码,就像典型的代码增长一样,您的测试最终需要进行重构才能实现可维护性和可持续性。有一吨GOTCHAS!当涉及到单元测试时,但男人哦,男人,男人,没什么,我的意思是没有让开发人员能够比一系列丰富的单元测试更自信地进行更改。
我现在正在开展一个项目......它有点像TDD,而且我们的大多数业务规则被视为测试...我们现在有大约500个左右的单元测试。在过去的迭代中,我不得不改进我们的数据源以及我们的桌面应用程序如何与该数据源进行交互。花了几天时间,我一直在进行单元测试,看看我打破了什么并修好了。做出改变;构建并运行测试;修复你破坏的东西。洗涤,冲洗,必要时重复。传统上需要几天的质量保证和船只压力是一种短暂而愉快的体验。
预先准备好一点额外的努力,当你不得不开始使用核心功能/功能时,它会付出10倍的代价。
我买了这本书 - 它是xUnit测试知识的圣经 - 可能是我书架上参考最多的书籍之一,我每天都会查阅:link text
答案 17 :(得分:7)
有时候,我自己或我的一个同事会花费几个小时到达稍微模糊的bug的底部,一旦发现错误的原因,90%的时间代码都没有经过单元测试。单元测试不存在,因为开发人员正在偷工减料以节省时间,但随后又失去了这个和更多的调试。
花费少量时间编写单元测试可以节省未来几小时的调试时间。
答案 18 :(得分:6)
我不知道。很多地方不做单元测试,但代码质量很好。微软确实进行了单元测试,但比尔盖茨在他的演讲中给出了蓝屏。
答案 19 :(得分:6)
当你说“我们的代码库不适合轻松测试”是代码味道的第一个迹象。编写单元测试意味着您通常以不同方式编写代码,以使代码更易于测试。在我看来,这是一件好事,因为我多年来在编写代码时已经看到了我必须编写的测试,这迫使我提出了更好的设计。
答案 20 :(得分:6)
单元测试绝对值得付出努力。不幸的是,您选择了一个难以实现的(但不幸的是常见的)场景。
从单元测试中获得的最大好处是从头开始使用它 - 在一些精选的小项目中,我很幸运能够在实现我的类之前编写单元测试(接口已经是完成此时)。通过适当的单元测试,您可以在课程中找到并修复错误,同时它们仍然处于初级阶段,而不是在复杂系统附近的任何地方,它们无疑将在未来集成。
如果您的软件是面向对象的,那么您应该能够在课程级别添加单元测试,而无需花费太多精力。如果您不是那么幸运,您仍应尝试在任何地方进行单元测试。确保在添加新功能时,新部件的界面清晰,界面清晰,您会发现单元测试使您的生活更加轻松。
答案 21 :(得分:5)
我写了一篇关于这个主题的非常大的博客文章。我发现单独的单元测试不值得工作,并且在截止日期越来越近时通常会被削减。
我们不应该从“测试后”验证的角度讨论单元测试,而应该看看在实现之前编写规范/测试/想法时发现的真实值。
这个简单的想法改变了我编写软件的方式,我不会回到“旧”的方式。
答案 22 :(得分:3)
我最近在我的工作场所经历了完全相同的经历,发现他们中的大多数人都知道理论上的好处,但必须特别以他们的利益出售,所以这里是我使用过的(成功):
和最重要的......
答案 23 :(得分:3)
是的 - 单位测试绝对是值得的,但你应该知道它不是一颗银弹。单元测试是有效的,你必须努力保持测试更新和相关的代码更改,但提供的价值是值得你付出的努力。重构的能力不受惩罚是一个巨大的好处,因为你总是可以验证功能通过在任何更改代码之后运行测试。诀窍是不要过于依赖于您正在测试的工作单元或者您是如何构建测试要求以及单元测试是否真的是功能测试等等。人们会争论这些东西几个小时最后,现实是你作为写代码做的任何测试都比不做它更好。另一个公理是关于质量而不是数量 - 我已经看到基于1000的测试的代码库本质上没有意义,因为其余的没有真正测试任何有用的或特定领域的特定领域,如特定领域的业务规则等。我还看到代码库有30%的代码覆盖率,但测试是相关的,有意义的,非常棒,因为他们测试了代码编写的代码的核心功能,并表达了应该如何使用代码。
在探索新的框架或代码库时,我最喜欢的一个技巧是为'it'编写单元测试以发现事情是如何工作的。这是了解更多关于新事物而不是阅读干燥文档的好方法:)
答案 24 :(得分:3)
没有人提到的一件事是让所有开发人员承诺实际运行和更新任何现有的自动化测试。由于新的开发而您回到并发现损坏的自动化测试会失去很多价值并使自动化测试变得非常痛苦。由于开发人员手动测试了代码,因此大多数测试都不会显示错误,因此更新它们所花费的时间只是浪费。
说服怀疑论者不破坏其他人在单元测试中所做的工作对于从测试中获取价值更为重要,而且可能更容易。
每次从存储库更新时,花费数小时更新因新功能而损坏的测试,既不高效又无趣。
答案 25 :(得分:3)
几年前我发现了TDD,并且已经使用它编写了我的所有宠物项目。我估计TDD项目花费大致相同的时间,因为它需要将牛仔放在一起,但我对最终产品的信心增强,我无法帮助你获得成就感。
我也觉得它改善了我的设计风格(更多面向界面,以防我需要一起模拟的东西),并且,正如顶部的绿色帖子写道,它有助于“编码便秘”:当你不'我知道接下来要写什么,或者你面前有一项艰巨的任务,你可以写小。
最后,我发现到目前为止TDD最有用的应用是在调试中,只是因为你已经开发了一个询问框架,你可以用它来刺激项目以可重复的方式产生bug。
答案 26 :(得分:2)
使用单元测试套件,可以对代码进行更改,同时保留其余功能。它的一大优势。在完成新功能的编码时,您是否使用单元测试sutie和回归测试套件。
答案 27 :(得分:2)
如果你正在使用NUnit,一个简单但有效的演示就是在它们面前运行NUnit自己的测试套件。看到一个真正的测试套件为代码库提供锻炼值得千言万语......
答案 28 :(得分:2)
我同意与大多数人相反的观点: It's OK Not to Write Unit Tests 特别是原型大量的编程(例如AI)很难与单元测试相结合。
答案 29 :(得分:2)
根据我的经验,单元测试和集成测试在复杂的软件环境中是“必须的”。
为了说服团队中的开发人员编写单元测试,您可能需要考虑在开发环境中集成单元测试回归分析(例如,在日常构建过程中)。
一旦开发人员知道如果单元测试失败,他们就不必花费太多时间来调试它来发现问题,他们会更鼓励他们编写它们。
这是一个提供此类功能的工具:
答案 30 :(得分:2)
关于单元测试要记住的一件事是,这对开发人员来说是一种安慰。
相比之下,功能测试适用于用户:每当您添加功能测试时,您都在测试用户将看到的内容。当您添加单元测试时,您只是让开发人员的生活更轻松。在这方面,这有点奢侈。
当您必须在编写单元或功能测试之间做出选择时,请记住这种二分法。
答案 31 :(得分:2)
单元测试在比任何一个开发人员都能掌握的项目中有很大帮助。它们允许您在签入之前运行单元测试套件,并发现您是否损坏了某些东西。这样可以减少批次,因为在等待其他人修复他们检查过的错误时,必须坐下来转动你的拇指,或者为了恢复他们的改变而烦恼,这样你就可以得到一些工作完成。它在重构方面也非常有价值,因此您可以确保重构的代码通过了原始代码所做的所有测试。
答案 32 :(得分:1)
单元测试的重点是简化测试。它是自动化的。 “做出测试”,你就完成了。如果您遇到的问题之一难以测试代码,那么这是所有使用单元测试的最佳理由。
答案 33 :(得分:1)
就在今天,我不得不改变之前编写过单元测试的课程 测试本身写得很好,包括我甚至没想过的测试场景 幸运的是,所有测试都通过了,我的更改得到了快速验证,并充满信心地进入了测试环境。
答案 34 :(得分:1)
@George Stocker“不幸的是,我们的代码库不适合轻松测试。”每个人都同意单元测试有好处,但听起来这个代码库的成本很高。如果成本高于收益,那么他们为什么要对此充满热情呢?听你的同事说;也许对于他们来说,单元测试的感知痛苦大于单元测试的感知价值。
具体来说,尝试尽快获得价值,而不是一些感觉狡猾的“xUnit是绿色”值,而是用户和维护者重视的干净代码。也许你必须为一次迭代强制进行单元测试,然后讨论是否值得努力。
答案 35 :(得分:1)
让您测试的第一件事与单元测试无关。我主要在Perl工作,因此这些是Perl特定的示例,但您可以适应。
每个模块都加载并正确编译吗?在Perl中,这是为代码库中的每个Foo.pm创建一个Foo.t的问题:
use_ok( 'Foo' );
是否所有POD(Plain Ol'文档)格式正确?使用Test :: Pod验证所有文件中所有POD格式的有效性。
你可能不认为这些是大事,但它们不是,但我可以保证你会抓住一些污点。当这些测试每小时运行一次,并且它会抓住某人的过早提交时,你会让人们说“嘿,这很酷。”
答案 36 :(得分:1)
单元测试的一个好处是可预测性。
在进行单元测试之前,我可以准确地预测编码内容需要多长时间,但不能预测调试它需要多长时间。
现在,由于我可以计划我要编写的测试,我知道编码需要多长时间,并且在编码结束时,系统已经调试好了!这为开发过程带来了可预测性,消除了很多压力,但仍然保留了所有的快乐!
答案 37 :(得分:1)
作为一名物理系学生,我非常想实际上证明我的代码按照预期运行。您可以在逻辑上证明这一点,随着实现变得更加复杂,这会大大增加难度,或者您可以通过良好的测试来制作(尽可能接近)功能的经验证明。
如果您不提供功能的逻辑证明,则必须进行测试。唯一的选择是说“我认为代码有效......”
答案 38 :(得分:1)
手动测试软件时,通常会使用一小组测试/操作。最终,您将自动变形您的输入数据或操作,以便您自己解决已知问题。单元测试应该在那里提醒你事情不能正常工作。
我建议在代码之前编写测试,添加新的测试/数据以改进主代码的功能!
答案 39 :(得分:0)
单元测试可帮助您以更少的错误发布软件,同时降低总体开发成本。您可以点击该链接,详细了解benefits of unit testing
答案 40 :(得分:0)
这是以.Net为中心的,但是有人试过 Pex 吗?
在我尝试之前,我非常怀疑 - 而且,哇,这是什么表现。在我开始思考之前“我不会被这个概念所说服,直到我理解它实际上做让我受益”。我花了一个小时才改变主意并说“我不关心你怎么知道那里有致命异常的风险,但是现在我知道我必须处理它“
这种行为的唯一不利方面是它会标记所有内容并给你一个六个月的积压。但是,如果你有代码债务,你总是有代码债务,你只是不知道它。在你知道几十个是一个令人讨厌的前景之前,告诉PM有潜在的二十万点失败,这意味着首先解释这个概念是至关重要的。
答案 41 :(得分:0)
你想说服谁?工程师或经理?如果您试图说服您的工程师同事,我认为您最好的选择是吸引他们制作高质量软件的愿望。有许多研究表明它发现了错误,如果他们关心做得好,那对他们来说应该足够了。
如果您试图说服管理层,您很可能必须做某种成本/收益推理,说明未检测到的缺陷成本高于编写测试的成本。一定要包括可扣除的费用,例如失去客户信心等等。
答案 42 :(得分:0)
单元测试是高质量代码最常用的方法之一。它对更稳定,独立和文档化的代码的贡献得到了充分证明。单元测试代码被视为存储库的一个组成部分,因此需要开发和维护。但是,开发人员经常会遇到这样一种情况:投入单元测试的资源并不像人们期望的那样富有成效。 在一个理想的世界中,我们编写的每个方法都会有一系列测试,覆盖它的代码并验证它的正确性。但是,通常由于时间限制,我们要么跳过一些测试,要么写出质量差的测试。在这样的现实中,在牢记投入单元测试开发和维护的资源量的同时,在给定可用时间的情况下,必须问自己哪个代码最值得测试?从现有的测试中,哪些测试实际上值得保留和维护?见here
答案 43 :(得分:-9)
单元测试适用于QA人员或您的经理,而不适合您;所以这绝对不值得。
你应该专注于编写正确的代码(无论它意味着什么),而不是测试用例。让其他人担心这些。