如何证明你写的代码没有BUG?
作为一个程序员,相信大家都有着一个信仰,那就是写出没有BUG的程序.那种在连续敲击上百行的代码,且编译运行都完美通过后的成就感.只有程序员才能体会得到
那么我们该如何写出一段"看起来没有bug",能成功交付给客户的程序呢?
先从一个典型的开发场景来讲一讲:
需求
我是一个Java程序员,我接了几个需求:
- 在web端分页展示数据库中所有的客户信息
- 用户可以根据条件查询符合要求的客户信息
不知道大家接到这样的需求是什么样的心情,反正我是很懵逼的…为什么呀?这个看起来不就是一个很简单的单表查询吗?怎就很懵逼了? 下面我就解释一下为什么.
- 这个需求的验收标准很模糊
- 分页参数是多少,分页参数异常怎么提示?
- 比如数据库有一个用户张三,姓名男,电话138******** ,我在表单上同时输入姓名张三,电话139******** 这样的情况怎么说,
- …
要是需求是这样子的,那就明白多了:
- 给定以下3个用户:
姓名 | 电话 | 性别 |
---|---|---|
张三 | 1381 | 男 |
李四 | 1382 | 女 |
王五 | 1383 | 女 |
- 当搜索条件是张三的时候,只显示出张三的信息
- 当搜索条件是 张三,电话138的时候,显示张三,李四,王五的信息
- …
这样的需求就清晰多了,不是吗?
开发调试
我花了九牛二虎之力和产品经理沟通,终于是弄清楚了整个需求,并且也很清楚的知道了我的目标,我要干嘛,我要写出什么样的程序.
创建pojo,dao,service,controller,一气呵成,总感觉他没有bug,但是又有点不自信…要不要往数据库插入几条模拟数据,来测试一下呢…感觉有点麻烦.说干就干.很快的就完成了,自己测试一遍,很完美.
刚准备提交代码,产品经理把我喊住,说,客户信息需要包含他们的个人征信的信息,最好加一个个人信用的字段排序,信用越好的,排序靠前…
这就麻烦了,我哪来的个人征信的数据,
又不能连表查询,不管了,不管了,先预留一个取征信数据的接口,然后造一波假数据.
- 我是直接在业务代码里面造假数据吗?
- 我实是在数据库里面造个人征信的假数据吗?
- 个人征信的数据一般是通过调用第三方接口来获取的吧
- 说到底,除了个人,其他人和组织都没办法获取其他人的征信信息吧.
- 我是真的纠结…
有咩有什么办法能不用再业务代码里面造假数据的方法?答案肯定是有的.
- 可以创建一个代理类来替代真实的业务类
- 在代理类中使用模拟数据实现获取个人征信的方法
那么问题来了,我这个代理类里面的模拟数据需要依赖数据库中的客户信息,不同的环境,测试结果可能还不相同.怎么保证测试数据即使在不同的环境里,也能达到相同的测试效果?
话说回来,我为啥子要为我写的代码做测试?还不是因为我不够自信.如果能亲眼见到这个程序最终的效果,我肯定会非常放心,非常肯定的大声跟测试人员说,我写的代码,你们随便测,测出一个bug算我输.
首先得实现一个代理类,然后用再spring容器中装载这个代理类,然后启动测试,经过漫长的等待终于是能见到测试结果了.
速度是程序员最大的敌人,每测试一个小小的功能都要等待30左右的时间取加载spring的bean,这是不合理的.一个小功能还好,但是数量一多,时间成本太过高昂了,久而久之,个人,公司都会放弃写单元测试,写出一大堆遗留代码…而且一大堆的模板代理类写的也是让人作呕哦
那有咩有方法能够有效降低测试成本呢,那肯定是有的嘛
- 启动单元测试的时候要是能不加载那么多spring的bean,时间肯定能节约下来
- 不访问数据库,文件系统,网络通信
仔细想一想,我们做spring项目的测试的时候,是否真的需要加载spring的bean.是否真的需要从数据库里面拿数据展示到页面才能完成测试?这个是单元测试吗?
单元测试
何谓单元测试?
之前看了一本书<测试驱动开发的艺术>,里面有这么一段定义:
- 访问了数据;
- 有网络通信;
- 访问了文件系统
- 不与其他任何单元测试同时运行
- 必须配置好环境后才能运行
只要一个测试满足以上任意一个,它都不是单元测试!
为什么需要写单元测试?
先看看写单元测试的好处:
- 单元测试不但会使你的工作完成得更轻松。而且会令你的设计会变得更好,甚至大大减少你花在调试上面的时间
- 提高代码质量
- 减少bug,快速定位bug
- 放心地修改、重构
- 提升对代码的信心
单元测试