引子
当我第一篇博客原题叫做<为什么. NET 开发者都不写单元测试>, 我的本意是想跟. NET 技术圈的朋友们一起交流, 为什么过去在. NET 开发中很少用到单元测试, 之后, 在公众号文章和博客园的留言中, 许多开发者纷纷表示, 单元测试作为企业行为, 与实施的技术栈不同, 不是开发者个人行为, 实施单元测试花费的时间精力过于庞大, 与实际效果严重不对等, 而且如果过度的采用单元测试, 也会增加新的测试点, 因为单元测试代码本身就需要进行测试等.
从这些回复可以看出, 程序员要不要编写单元测试这种话题, 大概做传统开发时, 问程序员要不要写项目文档一样充满争议. 正如大家都深刻明白项目文档的重要性, 但是一旦程序员需要编写项目文档了, 往往会对这个事情产生抵触情绪, 这实际上是绝大多数开发者的通病.
单元测试也是这样的矛盾纠结体. 在长沙. net 技术社区就有不少朋友纷纷表示, 他们都曾经试图在公司推动单元测试的应用, 但是受到了自上而下的反对声, 最终迫于压力, 只能放弃. 而之所以阻力这么大, 其主要原因是编写单元测试会增加额外的时间, 因为编写单元测试, 不仅仅只是编写一个简单的测试入口, 而是一系列步骤, 但是领导要求在最短的时间看到效果, 并且有的领导还经常改变主意, 如果设计了一个优秀的单元测试用例, 有时候甚至会因为无法适应需求的变化, 而最终腐烂.
显然, 使用单元测试和更高的单元测试的代码覆盖率, 大概是一个试金石. 过去在长沙还很少有企业会问开发者会不会使用单元测试, 但是近年来越来越多的企业会问候选人代码覆盖率的问题, 所以作为开发者, 可以尝试从单元测试开始, 努力提高自己的代码习惯, 编写更加高质量的代码.
有哪些公司在要求编写单元测试?
过去, 单元测试一直是专业软件公司的首选, 有一位原诺基亚核心部门的开发者说为诺基亚内部, 对单元测试的要求很高, 虽然没有达到百分之百, 但也有非常高的要求, 在《构建之法》中, 邹欣老师介绍了微软的开发实践, 也对单元测试覆盖率提出了很高的要求. 当然有的读者或许会嗤之以鼻, 这些都是古典软件公司, 举这些例子有什么意义呢? 中国式 IT 公司, 哪家都是 996, 哪里还有什么时间实行单元测试?
然而, 优秀的互联网公司都开始推行 devops 作为企业信息化建设过程中的最佳实践标准, 持续集成和持续发布都对单元测试有很高的要求, 例如在阿里巴巴 java 开发者手册中, 就明确提出了以下一系列指标, 要求开发者务必采用单元测试方法, 尽可能的提高代码质量.
[强制] 好的单元测试必须遵守 AIR 原则.
... 此处省略七百字
[推荐] 单元测试的基本目标: 语句覆盖率达到 70% ; 核心模块的语句覆盖率和分支覆盖率都要达到 100%
参见原文阿里巴巴 Java 开发者手册, 由此可见, 单元测试已经作为一种行之有效的手段, 显然已经成为了中国优秀互联网企业的必然之选.
单元测试中的代码覆盖率有什么用?
代码覆盖率是单元测试的重要衡量指标, 反映了单元测试中测试用例对被测代码的覆盖程度, 是对代码的测试质量衡量的重要指标.
在十年前, 博客园《代码覆盖率浅谈》(参考资料 1)一文, 深入浅出的介绍了单元测试的四种类型, 包括语句覆盖, 判定覆盖, 条件覆盖, 路径覆盖四种类型, 作者指出, 单元测试覆盖率结果, 有以下作用:
a. 覆盖率数据只能代表你测试过哪些代码, 不能代表你是否测试好这些代码.
b. 不要过于相信覆盖率数据.
c. 不要只拿语句覆盖率 (行覆盖率) 来考核你的测试人员.
d. 路径覆盖率> 判定覆盖> 语句覆盖
e. 测试人员不能盲目追求代码覆盖率, 而应该想办法设计更多更好的案例, 哪怕多设计出来的案例对覆盖率一点影响也没有.
在软件开发过程中盲目的追求的高代码覆盖率, 往往得不偿失, 尤其是为了提高代码覆盖率而做的单元测试, 往往只会成为累赘.
合理的操作形式应该是基于实际用例出发, 设定更多的用例场景, 实现基于用户场景驱动的单元测试覆盖, 像在阿里巴巴开发者手册中说的, 测试人员与开发人员配合, 共同完成测试用例覆盖, 就是一种不错的应用实践.
当然, 即便测试缺位, 开发者也完全应该主动的承担更多单元测试的职能, 尽可能多的思考用户场景中可能存在的变数.
编写好的单元测试的一些小技巧
技巧一, 多看书肯定是不错的
有朋友问, 怎么写好单元测试? 有什么书推荐么? 我很惭愧, 我自己的代码单元测试的覆盖率还相当低, 可能没办法给出指导, 我想多看书肯定是没错的, 而编写单元测试的书, 还挺多的, 例如这一本,《单元测试的艺术》, 一看就是基于 C# 的, 可以试一试.
而想入单元测试的门, 可以看看我后面找到的一系列引文, 相信能给你带来方便.
技巧二, 运用测试框架
1, 单元测试框架: XUnit,NUnit,MSTest 等.
2, 测试运行工具: xunit.runner.visualstudio . 类似如: Resharper 的 xUnit runner 插件.
3, 模拟框架: Moq,RhinoMocks,NSubstitute,FakeItEasy 等.
技巧三, 灵活的运用事务回滚或内存数据库, 避免单元测试数据污染正常数据
前者是阿里巴巴开发者手册中提到的一种方法, 在有的场景下也挺实用的, 不过有开发者指出, 可以使用模拟内存数据库来解决这个问题更为妥当, 例如使用 Effort.EF6, 通过 nuget 获取, 使得创建一个伪造的, 供 EF 容易使用的内存数据库成为可能. 与这类似的, 还可以使用 HttpSimulator 来模拟 http 请求.
技巧四, 使用依赖注入和单例模式改良不可测代码
静态类为代码编写带来了许多便利, 但是也使得代码测试变得相对困难, 而使用单例模式进行改良则使得操作更可控.
总结
人生苦短, 撸码不易. 从选择成为开发者的那一天起, 我们就被迫承受了许多压力, 尤其是技术发展的不确定性, 更是如此, 你永远也不知道自己当下的选择是否正确, 说不定你今天最为熟悉的技术或框架, 明天就凉凉了. 尤其是现在的各种自媒体, 时不时的发几篇文章来输出焦虑, 巴不得天天说优胜劣汰才能获得读者的关注一般, 让开发者们压力更大.
我觉得, 技术是解决问题的方法, 而良好的代码习惯则是自身心法, 尤其是单元测试, 更是一种好习惯, 先别总想着担心自己被淘汰, 努力的使自己习惯更好, 总会获得无穷收获.
参考资料 1:《代码覆盖率浅谈》.
参考资料 2:《代码覆盖率强迫症 https://www.infoq.cn/article/test-coverage-ocd 》.
参考资料 3: 《代码覆盖率 (Code Coverage)从简到繁》
参考资料 4,《C# 单元测试, 带你快速入门》.
来源: https://www.cnblogs.com/xiyuanMore/p/10667988.html