什么是单元测试?

Ube*_*zzy 208 glossary unit-testing

我看到很多问题询问'如何'用特定的语言进行单元测试,但毫无疑问,问'什么','为什么'和'什么时候'.

  • 它是什么?
  • 它对我有什么用?
  • 我为什么要用它?
  • 我什么时候应该使用它(当不是时)?
  • 有哪些常见的陷阱和错误观念

Ryt*_*mis 196

粗略地说,单元测试是用测试代码单独测试代码的一部分.想到的直接好处是:

  • 运行测试变得可自动化且可重复
  • 您可以通过GUI进行比点击式测试更精细的测试

请注意,如果您的测试代码写入文件,打开数据库连接或通过网络执行某些操作,则更适合将其归类为集成测试.集成测试是一件好事,但不应与单元测试混淆.单元测试代码应该简短,甜蜜且快速执行.

查看单元测试的另一种方法是首先编写测试.这被称为测试驱动开发(简称TDD).TDD带来了额外的优势:

  • 你不会写出推测性的"我将来可能需要这个"代码 - 这足以让测试通过
  • 您编写的代码总是由测试覆盖
  • 通过首先编写测试,您不得不考虑如何调用代码,从长远来看,这通常会改进代码的设计.

如果您现在没有进行单元测试,我建议您开始使用它.得到一本好书,几乎任何xUnit-book都会做,因为这些概念在它们之间是可以转移的.

有时编写单元测试可能会很痛苦.当它成功的时候,试着找人来帮助你,并抵制"只写那该死的代码"的诱惑.单元测试就像洗碗一样.它并不总是令人愉快,但它让你的隐喻厨房变得干净,你真的希望它变得干净.:)


编辑:脑海中浮现出一种误解,虽然我不确定它是否如此常见.我听说项目经理说单元测试让团队编写了两次所有代码.如果它看起来和感觉那样,那么,你做错了.编写测试通常不仅可以加快开发速度,而且还可以为您提供一个方便的"现在我已经完成"的指标,否则您就不会这样做.

  • 您是否会提出关于TDD如何加速开发的观点? (2认同)

Kar*_*uin 69

我不同意丹(虽然更好的选择可能只是不回答)......但......

单元测试是编写代码以测试系统行为和功能的过程.

显然,测试可以提高代码的质量,但这只是单元测试的一个表面上的好处.真正的好处是:

  1. 在确保不改变行为(重构)的同时,更容易更改技术实现.正确的单元测试代码可以被积极地重构/清理,几乎没有机会在不注意的情况下破坏任何东西.
  2. 在添加行为或修复时为开发人员提供信心.
  3. 记录您的代码
  4. 指示代码紧密耦合的区域.单元测试紧密耦合的代码很难
  5. 提供一种使用API​​的方法,并尽早寻找困难
  6. 表示不具有凝聚力的方法和类

您应该进行单元测试,因为您有兴趣为您的客户提供可维护和优质的产品.

我建议你将它用于任何系统或系统的一部分,它可以模拟真实世界的行为.换句话说,它特别适合企业发展.我不会将它用于丢弃/实用程序.我不会将它用于测试有问题的系统部分(UI是一个常见的例子,但情况并非总是如此)

最大的缺陷是开发人员测试的单元太大,或者他们认为方法是一个单元.如果您不了解控制反转,则尤其如此- 在这种情况下,您的单元测试将始终转变为端到端集成测试.单元测试应测试个人行为 - 大多数方法都有很多行为.

最大的误解是程序员不应该测试.只有糟糕或懒惰的程序员才会相信.建造屋顶的人不应该测试吗?更换心脏瓣膜的医生是否应该测试新的瓣膜?只有程序员才能测试他的代码是否按照他的意图进行测试(QA可以测试边缘情况 - 代码在被告知做程序员不想要的事情时的行为,客户端可以进行验收测试 - 代码是否执行客户支付的费用是什么)


Pét*_*rök 44

与"仅打开一个新项目并测试此特定代码"相反,单元测试的主要区别在于它是自动化的,因此是可重复的.

如果您手动测试代码,它可能会让您确信代码运行正常 - 处于当前状态.但是一周后,当你对它做了一点修改时呢?您是否愿意在代码中发生任何变化时再次手动重新测试?最有可能不是:-(

但是,如果您可以随时运行测试,只需单击一次,几秒钟内完全相同,那么无论何时出现问题,他们都会立即向您显示.如果你还将单元测试集成到你的自动构建过程中,他们会提醒你注意错误,即使在一个看似完全不相关的变化破坏了代码库的一个遥远的部分 - 甚至在你甚至不会发生的情况下需要重新测试该特定功能.

这是单元测试优于手动测试的主要优点.但等等,还有更多:

  • 单元测试显着缩短了开发反馈循环:对于单独的测试部门,您可能需要数周时间才能知道代码中存在错误,此时您已经忘记了大部分上下文,因此可能需要数小时才能完成找到并修复bug; OTOH通过单元测试,反馈周期以秒为单位进行测量,错误修复过程通常沿着"哦sh*t,我忘了在这里检查那个条件":-)
  • 单元测试有效地记录(您的理解)代码的行为
  • 单元测试迫使您重新评估您的设计选择,从而使设计更简单,更清洁

反过来,单元测试框架使您可以轻松编写和运行测试.


Cod*_*tch 33

我从未在大学教过单元测试,我花了一段时间才"搞定"它.我读到了它,"啊,对,自动测试,我觉得这很酷",然后我就忘记了.

在我真正弄清楚这一点之前花了相当长的时间:让我们说你正在研究一个大型系统并且你编写了一个小模块.它编译,你通过它的步伐,它工作得很好,你继续下一个任务.九个月后,有两个版本,其他人改变了一些看似无关的程序部分,它打破了模块.更糟糕的是,他们测试他们的更改,他们的代码是有效的,但他们不测试你的模块; 他们甚至不知道你的模块是否存在.

而现在你遇到了一个问题:破解的代码在主干中,甚至没有人知道.最好的情况是内部测试人员在你发货之前找到它,但修复游戏后期的代码是昂贵的.如果没有内部测试人员发现它......那么,确实会变得非常昂贵.

解决方案是单元测试.当你编写代码时,它们会遇到问题 - 这很好 - 但你可以手工完成.真正的回报是,当你现在正在开展一个完全不同的项目时,他们会在九个月后遇到问题,但是一个暑期实习生认为如果这些参数按字母顺序排列会更整洁 - 然后是单元测试你写回来的方法失败了,有人向实习生抛出东西,直到他改变参数顺序为止.就是单元测试的"原因".:-)


ree*_*lex 13

关于单元测试和TDD的哲学专业知识,这里有一些关键的"灯泡"观察,这些观察让我在TDD启蒙的道路上暂时迈出了初步的步伐(没有原创或必然的消息)......

  1. TDD并不意味着写入两倍的代码量.测试代码通常可以非常快速且轻松地编写,并且是设计过程的关键部分,也是批判性的.

  2. TDD可以帮助您实现何时停止编码!你的测试让你相信你已经做了足够的事情,可以停止调整并继续下一步.

  3. 测试和代码协同工作以实现更好的代码.你的代码可能很糟糕/错误.你的测试可能很糟糕/错误.在TDD中,你可以看出两个人很差/错误的可能性很小.通常它的测试需要修复,但仍然是一个很好的结果.

  4. TDD有助于编码便秘.你知道你觉得你有很多事要做,你几乎不知道从哪里开始?这是星期五下午,如果你拖延几个小时...... TDD可以让你很快充实你认为你需要做的事情,并让你的编码迅速发展.此外,就像实验室老鼠一样,我想我们都会回应那个大绿灯,并且更加努力地再次看到它!

  5. 同样,这些设计师类型可以看到他们正在做的工作.他们可以徘徊在果汁/香烟/ iphone休息时间,并返回显示器,立即给他们一个关于他们到达的地方的视觉提示.TDD给了我们类似的东西.生活介入时,我们更容易看到我们到达的地方......

  6. 我认为Fowler说:"不完美的测试,经常运行,比完全没有写过的完美测试要好得多".我将此解释为允许我编写测试,即使我的其余代码覆盖率非常不完整,我认为它们也是最有用的.

  7. TDD以各种令人惊讶的方式提供帮助.良好的单元测试可以帮助记录应该做的事情,它们可以帮助您将代码从一个项目迁移到另一个项目,并给您一种无理感的优势,而不是非测试同事:)

本演示文稿是对所有美味良好测试需求的精彩介绍.


Pau*_*ndt 7

我想推荐Gerard Meszaros的xUnit Testing Patterns一书.它很大但是在单元测试方面是一个很好的资源.这是他的网站的链接,他在那里讨论了单元测试的基础知识. http://xunitpatterns.com/XUnitBasics.html


Lea*_*eah 5

我使用单元测试来节省时间.

在构建业务逻辑(或数据访问)时,测试功能通常涉及在很多可能已完成或可能尚未完成的屏幕中输入内容.自动化这些测试可节省时间.

对我来说,单元测试是一种模块化的测试工具.每个公共职能通常至少有一个测试.我写了额外的测试来涵盖各种行为.

您在开发代码时考虑的所有特殊情况都可以记录在单元测试的代码中.单元测试也成为如何使用代码的示例源.

对我来说,发现我的新代码在我的单元测试中破坏了某些内容然后检查代码并让一些前端开发人员发现问题要快得多.

对于数据访问测试,我尝试编写无需更改或自行清理的测试.

单元测试无法解决所有测试要求.他们将能够节省开发时间并测试应用程序的核心部分.