刚开始工作的时候对单元测试是一种神秘主义,觉得测试很好,但不知道如何开始。团队里也没人去写单元测试,偶尔有个也是写的集成测试,用Spring的test,将所有依赖注入进来,然后System.out.println
输出肉眼观测数据是否符合要求,这让我对测试有向往,但是又嫌麻烦,毕竟这样测试写了很多的代码,但是速度上、准确性上都达不到要求。
就这样一直手动测试了很长时间,也听多了单元测试,自动化测试等等名词,却一直不得其门而入。买过一本单元测试相关的书,看完了,但就是没有开窍。去开发者头条上搜相关测试主题,讲的都是一些思想上的,对我目前的疑惑却没有什么帮助,毕竟我还没有入门。
后来忘了在哪又看到了单元测试的定义:是对一个模块,一个类或一个函数的正确性做检测的测试工作。突然有点明白了如何来写单元测试,以往一直迷惑这么多依赖该怎么办,覆盖不到全部执行路径怎么办,看到一个函数
这四个字我找到了答案:一个函数依赖不会很多,可以使用mock来解决;一个函数的全部执行路径也就那么多,每种情况都考虑到也不会很多;前面说的使用System.out.println
肉眼测试,也因为函数只有一个返回值而可以使用Assert
类来断言来判断正确性。关键就在于单元,一开始把目光着眼在一个服务类上,依赖十几个服务,几十个外部函数调用,使我望而却步,而把焦点放到函数上,一来可以避免自己写超大的函数,二来依赖少,写单元测试的阻力变小了。
很多人会说测试的目的当然是保证程序的正确性,恰恰相反,作为开发和测试,我们测试的目的是为了找出程序中包含的错误,也就是测试是为了弄垮软件,测试没有发现错误说明测试用例是无效的或不完整的(Code complete).
你必须期望代码里有错误,期望发现错误的那个人是你而不是其他人。
在这Code Complete中给了我们一个测试中用例的最少数量计算方法:
按照这种方法,基础的代码路径覆盖已经达到了,但在复杂程序里譬如for中包含多个if的情况需要添加更多的测试用例,CC中给出了数据流测试,这里不再赘述,因为我觉得如果你的函数连基础测试用例都十几个的话,你该考虑的不是添加更多的测试,而是如何拆分这个函数了。
单元测试是开发保证自己工作质量的一个有力工具,在我看来,写单元测试要比靠手工去测试花费的时间少,效率高,修改方便。甚至在数据构造上,单元测试也比手工测试要方便快捷,毕竟页面上每次你都要把需要的数据都准备一遍,在代码里你需要修改的可能也就是两三处地方。