关于单元测试,什么不测试?
在项目编写的哪些部分进行单元测试几乎或者实际上是不可能的?数据访问? FTP?
如果对此问题有一个答案,那么%100的承保范围就是一个神话,不是吗?
解决方案
可以进行数据访问,因为我们可以设置测试数据库。
通常,"无法使用"的内容是FTP,电子邮件等。但是,它们通常是我们可以依赖的框架类,因此不需要测试是否将它们隐藏在抽象后面。
而且,仅靠100%的代码覆盖率还不够。
如果设置单元测试所需状态的代码比要测试的代码复杂得多,那么我倾向于划清界限,并找到另一种方法来测试功能。在这一点上,我们必须问我们如何知道单元测试是正确的!
100%的覆盖率只是一个神话,并不意味着80%的覆盖率是无用的。当然,目标是100%,在单元测试和集成测试之间,我们可以实现它。
在单元测试中不可能做到的是预测客户对产品所做的所有奇特的事情。一旦开始发现代码的这些令人难以置信的变态,请确保将针对它们的测试回滚到测试套件中。
任何需要非常大而复杂的设置的事情。当然,我们可以测试ftp(客户端),但随后需要设置ftp服务器。对于单元测试,我们需要可重现的测试设置。如果无法提供,则无法测试。
实现100%的代码覆盖率几乎总是很浪费。有很多资源。
没有什么是不可能进行单元测试的,但是总会有收益递减的情况。对单元测试感到痛苦的事情进行单元测试可能不值得。
@加里·舒特勒
我实际上是通过使用伪造的smtp服务器(Wiser)对电子邮件进行单元测试的。确保应用程序代码正确:
http://maas-frensch.com/peter/2007/08/29/unittesting-e-mail-sending-using-spring/
类似的事情可能可以在其他服务器上完成。否则,我们应该能够模拟API ...
顺便说一句:100%的覆盖率仅仅是个开始……仅意味着所有代码实际上都已执行一次Bean ....关于边缘情况等都没有。
我们可以使用服务器仿真来测试FTP,电子邮件等。这是困难的,但可能的。
无法测试的是一些错误处理。在每个代码中都有永远不会发生的错误处理。例如,在Java中,必须捕获很多异常,因为它是接口的一部分。但是用过的实例将永远不会抛出它。如果存在所有可能的情况,则为开关的默认情况。
当然,可以删除一些不需要的错误处理。但是将来会出现编码错误,那么这是不好的。
我们不会测试什么?任何不可能破坏的东西。
当涉及到代码覆盖率时,我们要针对实际编写的100%的代码,而无需测试第三方库代码或者操作系统代码,因为该代码已经交付给我们进行了测试。除非不是这样。在这种情况下,我们可能需要对其进行测试。或者,如果存在已知的错误,在这种情况下,我们可能需要测试错误的存在,以便获得有关何时修复的通知。
大多数需要庞大而昂贵(在资源或者计算时间方面)设置的测试都是集成测试。单元测试(理论上)应仅测试代码的小单元。个别功能。
例如,如果我们正在测试电子邮件功能,则创建模拟邮件程序是有意义的。该模拟的目的是确保代码正确调用邮件程序。查看应用程序是否实际发送邮件是一项集成测试。
区分单元测试和集成测试非常有用。单元测试应该运行非常快。在签入代码之前,应该可以轻松地运行所有单元测试。
但是,如果测试套件包含许多集成测试(用于设置和拆除数据库等),则测试运行时间很容易超过半小时。在这种情况下,开发人员很有可能在签入之前不会运行所有单元测试。
因此,请回答问题:做网络单元测试,最好将其作为集成测试来实现(也不要测试吸气剂/装填剂,这是浪费时间;-))。
首先对单元代码进行单元测试的主要原因是要验证代码的设计。可能会获得100%的代码覆盖率,但并非没有使用模拟对象或者某种形式的隔离或者依赖注入。
请记住,单元测试不是针对用户的,而是针对开发人员和构建系统的,可用于在发布之前验证系统。为此,单元测试应运行得非常快,并且配置和依赖关系的摩擦应尽可能小。尝试在内存中尽力而为,并避免使用测试中的网络连接。
我们可以对其进行测试,但是它们将不是单元测试。单元测试是跨界的,例如跨网,访问数据库,与第三方运行/交互,接触未经测试/传统的代码库等。
除此之外,还可以进行集成测试。
标题中问题的显而易见的答案是:我们不应该对API的内部进行单元测试,不应该依赖他人的行为,也不应该对不负责的任何事情进行测试。
剩下的应该足以使我们能够在其中编写代码,而不是更多,更少。
在大型项目上工作时,确保100%的覆盖率是一个不错的目标,但是对于大多数项目而言,在部署之前修复一两个bug并不一定值得花时间创建详尽的单元测试。
详尽测试表单提交,数据库访问,FTP访问等内容通常只是浪费时间;除非编写的软件需要很高的可靠性(99.999%的工作量),否则过多的单元测试可能会导致过大的杀伤力和实时的沉没。
我想,GUI的单元测试也很困难,尽管不是不可能。
在单元测试中,我们不应测试任何不属于单元的东西。在上下文中测试单元是另一回事。那是简单的答案。
我使用的基本规则是,我们应该对任何涉及单元边界的东西进行单元测试(通常是类,或者单元可能是其他任何东西),然后对其余部分进行模拟。无需测试某些数据库查询返回的结果,只需测试设备发出正确的查询即可。
这并不意味着我们不应该忽略难以测试的内容;使用正确的工具,甚至可以很好地测试异常处理和并发问题。
"关于单元测试,什么不应该测试?"
*带有getter和setter的Bean。推理:通常会浪费时间,最好花一些时间测试其他东西。
目标不是100%的代码覆盖率,也不是80%的代码覆盖率。易于编写的单元测试并不意味着我们应该编写它,而难以编写的单元测试并不意味着我们应该避免这种工作。
任何测试的目的都是以最友好的方式检测用户可见的问题。
由测试标记的创作,维护和诊断问题的总成本(包括误报)是否值得特定测试抓住的问题?
如果测试发现的问题是"昂贵的",那么我们可以付出努力找出如何测试并维护该测试。如果测试中发现的问题是微不足道的,那么编写(并维护!)测试(即使存在代码更改)也将变得微不足道。
单元测试的核心目标是保护开发人员免受实现错误的影响。仅此一项就表明过多的努力将是浪费。在确定的时间点之后,有更好的策略来获得正确的实施。同样,在某一点之后,用户可见的问题是由于正确实施了错误的操作而引起的,而错误的操作只能由用户级别或者集成测试来发现。
在这里,我发现(通过嘲笑迈克尔·费瑟斯所说的话可以得到答案:
他说,
A test is not a unit test if: It talks to the database It communicates across the network It touches the file system It can't run at the same time as any of your other unit tests You have to do special things to your environment (such as editing config files) to run it.
他在同一篇文章中再次补充:
Generally, unit tests are supposed to be small, they test a method or the interaction of a couple of methods. When you pull the database, sockets, or file system access into your unit tests, they are not really about those methods any more; they are about the integration of your code with that other software.
我不同意quamrana关于不测试第三方代码的回答。这是单元测试的理想用途。如果在新版本的库中引入了错误,该怎么办?理想情况下,当发布新版本的第三方库时,我们运行代表该库预期行为的单元测试,以验证其仍按预期运行。
配置是另一个很难在单元测试中进行良好测试的项目。集成测试和其他测试应针对配置进行。这减少了测试的冗余,并节省了大量时间。尝试进行单元测试配置通常很琐碎。
任何不能完全确定性的事情对于单元测试都是不可行的。如果像线程,随机数据生成,时间/日期或者外部服务之类的怪异现象会影响到这一点,那么我们希望单元测试始终以相同的初始条件通过或者失败,那么我们就不应在单元测试中进行介绍。时间/日期是一个特别令人讨厌的情况。通常,我们可以设计代码来确定要注入的日期(通过代码和测试),而不是依赖当前日期和时间的功能。
话虽这么说,单元测试不应该是应用程序中唯一的测试级别。实现100%的单元测试覆盖率通常是浪费时间,并且很快会遇到收益递减的情况。
更好的是拥有一组更高级别的功能测试,甚至是集成测试,以确保系统"一旦全部连接"就可以正常工作,而按定义,单元测试不会对此进行测试。
通常应使用接口测试FTP,SMTP,I / O。该接口应通过适配器(用于实际代码)和用于单元测试的模拟程序来实现。
任何单元测试都不应使用实际的外部资源(FTP服务器等)