最近在给一个客户作技术咨询,而后发现了客户对于单元测试的一个有意思的现象。分享出来,你们一块儿学习探讨一下。html
这里以java后端项目例,发现客户写的测试长下面的样子。(代码已经脱敏处理过。)java
@Autowired private SampleJob handler; @Test public void testStart() throws Exception { SampleParamVo paramVo = new SampleParamVo(); paramVo.setStartTime("2021-03-18"); paramVo.setEndTime("2021-03-18"); handler.execute(paramVo); }
@Autowired private SampleHandler handler; @Test public void testHandler() { handler.doHandler(new DateTime("2021-11-26"), null); }
那么这样的测试代码有什么问题呢?编程
@Autowired
这样的代码,增长了测试的耦合以及编写成本。和客户深聊了以后发现,原来客户不一样的人对单元测试的理解也不同。后端
因此咱们能够发现,有的开发人员口中的单元测试其实应该属于集成测试或者E2E测试,有的开发人员彻底没有写过单元测试,而测试人员理解单元测试是本身手动测试的时候用的测试用例。框架
那咱们就先来讲说什么是单元测试。ide
单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。
一般在java的世界里面,单元测试就是指对一个public
的方法编写检查和验证的代码。函数
写单元测试主要有两大目的:微服务
当咱们写完一个方法,咱们如何知道本身写的方法是定期望工做的呢?这个时候就能够添加单元测试来验证咱们的代码是定期望工做的。即当咱们给定指定的输入,咱们得到指望的输出,则咱们说这个功能是符合指望的。单元测试
其次,代码不是写了就永远不变的,当需求变动时,新增需求时,修复bug时,都会修改代码,而单元测试则能保护咱们已有的功能不被破坏。保护已有功能不会被本身破坏,被新人破坏,被新功能破坏。学习
下面是一个单元测试的例子
@Test public void should_return_fizz_given_input_can_be_divided_by_3() { FizzBuzz fizzBuzz = new FizzBuzz(); // Given String actual = fizzBuzz.sayIt(6); // When Assertions.assertEquals("Fizz", actual); // Then }
一个标准的单元测试包含如下几个部分:
单元测试的Given、When、Then具体内容。
写好单元测试要主要几个要点:
单元测试一般须要覆盖大量的case来保证咱们的代码在绝大多数场景下都是定期望工做的。所以要作到这一点能够参考下面两大原则。这里就不详细讲解这两个原则,具体内容能够Google。
单元测试有一个考核的标准就是测试覆盖率,指的是咱们的代码有百分之多少被单元测试测到了。
说到单元测试,就不得不提测试金字塔,以下图,最底层是单元测试,最顶层是UI测试。(测试金字塔有好几种,但道理都是相通的)
看左边的箭头,越往下越快,越往上越慢,它主要包括编写越快,运行越快,定位问题越快等。
看右边的箭头,越往下成本越低,越往上成本越高,包括时间成本,金钱成本,人员成本,维护成本等。
咱们在作单元测试的时候,经常可能访问外部系统或者外部类,这些外部的不可控性会让咱们的单元测试成本变得很高。
常见的外部不可控性有:HTTP访问,增删文件,随机性,时间相关性,接口类等。
因而开发者便开始探索更廉价的方式来写单元测试,mock就是其中的解决方案。
mock 对象运行在本地彻底可控环境内,利用 mock 对象模拟被依赖的资源,使开发者能够轻易的建立一个稳定的测试环境。
mock是Test double理论中的一种,若是对test double理论感兴趣,能够到这里了解更多,这里就不展开说了。
仍是以java为例,java的世界中经常使用的mock框架好比mockito。
下面是一个mock的例子。
@Test void should_return_100_when_get_list_size() { List map = mock(List.class); //当调用list.size()方法时候,返回100 when(map.size()).thenReturn(100); Assert.assertEquals(100, map.size()); }
单元测试是咱们测试的最小单位,所以咱们只测当前这个public
的方法中的实现,而方法中调用第三方类的东西,咱们都应该mock掉。
这样的好处有两个:
最后再升华一下,简单说一说TDD,TDD的全称是Test driven development,即测试驱动开发。它是极限编程XP中的一个标准实践。
TDD要求在编写某个功能的代码以前先编写测试代码,而后只编写使测试经过的功能代码,经过测试来推进整个开发的进行。
这样作有四大好处:
这里我就不详细叙述TDD相关的话题了,由于TDD是一个比较大的话题,若是感兴趣,下次专门开一个新话题来聊TDD。