为什么我们要做单元测试?(二)

引子

当我第一篇博客发布,并被张善友老师的公众号转载之后,在公众号文章和博客园的留言中,许多开发者纷纷表示,单元测试作为企业行为,与实施的技术栈不同,不是开发者个人行为,实施单元测试花费的时间精力过于庞大,与实际效果严重不对等,而且如果过度的采用单元测试,也会增加新的测试点,因为单元测试代码本身就需要进行测试等。

 从这些回复可以看出,程序员要不要编写单元测试这种话题,大概做传统开发时,问程序员要不要写项目文档一样充满争议。正如大家都深刻明白项目文档的重要性,但是一旦程序员需要编写项目文档了,往往会对这个事情产生抵触情绪,这实际上是绝大多数开发者的通病。

单元测试也是这样的矛盾纠结体在长沙.net技术社区就有不少朋友纷纷表示,他们都曾经试图在公司推动单元测试的应用,但是受到了自上而下的反对声,最终迫于压力,只能放弃。 而之所以阻力这么大,其主要原因是编写单元测试会增加额外的时间,因为编写单元测试,不仅仅只是编写一个简单的测试入口,而是一系列步骤,但是领导要求在最短的时间看到效果,并且有的领导还经常改变主意,如果设计了一个优秀的单元测试用例,有时候甚至会因为无法适应需求的变化,而最终腐烂。 

显然,使用单元测试和更高的单元测试的代码覆盖率,大概是一个试金石。过去在长沙还很少有企业会问开发者会不会使用单元测试,但是近年来越来越多的企业会问候选人代码覆盖率的问题,所以作为开发者,可以尝试从单元测试开始,努力提高自己的代码习惯,编写更加高质量的代码。

有哪些公司在要求编写单元测试?

过去,单元测试一直是专业软件公司的首选,有一位原诺基亚核心部门的开发者说为诺基亚内部,对单元测试的要求很高,虽然没有达到百分之百,但也有非常高的要求,在《构建之法》中,邹欣老师介绍了微软的开发实践,也对单元测试覆盖率提出了很高的要求。 当然有的读者或许会嗤之以鼻,这些都是古典软件公司,举这些例子有什么意义呢?中国式IT 公司,哪家都是996,哪里还有什么时间实行单元测试? 

然而,优秀的互联网公司都开始推行devops 作为企业信息化建设过程中的最佳实践标准,持续集成和持续发布都对单元测试有很高的要求,例如在阿里巴巴java 开发者手册中,就明确提出了以下一系列指标,要求开发者务必采用单元测试方法,尽可能的提高代码质量。

  1. 【强制】好的单元测试必须遵守 AIR 原则。

  2. ...此处省略七百字

  3. 【推荐】单元测试的基本目标:语句覆盖率达到 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:《代码覆盖率浅谈》https://www.cnblogs.com/coderzh/archive/2009/03/29/1424344.html?tt_from=copy_link&utm_source=copy_link&utm_medium=toutiao_ios&utm_campaign=client_share.

参考资料2:《代码覆盖率强迫症》https://www.infoq.cn/article/test-coverage-ocd.
参考资料3:《
代码覆盖率 (Code Coverage)从简到繁

https://www.cnblogs.com/jacksundatashare/p/5083352.html.
参考资料4,《
C#单元测试,带你快速入门http://www.cnblogs.com/zhaopei/p/UnitTesting.html?from=singlemessage&isappinstalled=0.

码字不易啊..哈哈smiley_21.png

(本文是作者为社区贡献的内容,赞赏的所有费用都将作为长沙.NET技术社区运营费用,感谢您的关注,让我们一起努力,共同创造长沙.NET技术社区更好的明天)


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/316394.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[CF1368E] Ski Accidents(神仙结论构造)

problem CF1368E Ski Accidents solution 这个 47n\frac 47n74​n 的限制,提示这存在一个特定构造方案,由 777 我们联想到 124712471247。 暗示把顶点分为三类 A,B,CA,B,CA,B,C,满足 ∣C∣≤2∣B∣≤4∣A∣|C|\le 2|B|\le 4|A|∣C∣≤2∣…

P4159 [SCOI2009] 迷路

P4159 [SCOI2009] 迷路 题意: 该有向图有 n 个节点,节点从 1 至 nn 编号,windy 从节点 1 出发,他必须恰好在 t 时刻到达节点 n。 现在给出该有向图(带边权),你能告诉 windy 总共有多少种不同的路径吗? …

程序员修神之路--提高网站的吞吐量

点击上方蓝色字体,关注我们菜菜哥,有个事你还得帮我呀呦西,YY妹子,最近天这么热了,你怎么还穿这么多?苦笑一下.....前几天写了几个接口,领导让提高一下接口吞吐量这是你技术提高的大好机会呀可吞…

P2151 [SDOI2009]HH去散步

P2151 [SDOI2009]HH去散步 题意: HH有个一成不变的习惯,喜欢饭后百步走。所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离。 但是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回…

Function Query(树状数组)

problem 给定一个长度为 nnn 的排列 aaa。有 qqq 个询问,每次询问一个区间 [l,r][l,r][l,r]。求这个区间的 kkk 值。 其中 k∑ilr∑ji1rf(ai,aj),f(x,y)k\sum_{il}^r\sum_{ji1}^rf(a_i,a_j),f(x,y)k∑ilr​∑ji1r​f(ai​,aj​),f(x,y) 为一个递归函数&#xff0c…

一份.NET 容器化的调查小结

小编在上个月在微信公众号“dotnet跨平台” 做了一个针对.NET 容器化的调查:.NET Core 容器化调查,参与人数702人,由于软件定义基础设施方兴未艾,编排和自动化领域kubernetes占据了主体地位,在平时的工作中和身边的同学…

P2148 [SDOI2009]ED

P2148 [SDOI2009]E&D 题意: 有2n堆石子,第2k-1堆和第2k堆是一组,现在两个人轮流操作,每次操作任选一组石子,然后将改组中的一堆石子移走,将另一堆式子分割成两堆,形成新的两堆石子&#x…

扒一扒.NET Core的环境配置提供程序

前言很久之前,在玩Docker的时候顺便扒了扒,最近,终于下定决心花了些时间整理并成文,希望能够给大家一些帮助。目录 .NET Core中的配置ASP.NET Core中的配置扒一扒环境变量提供程序为什么是“__”?“__”如何变成了“&…

[HNOI2016] 序列(线段树 + 莫队 + 倍增)

problem luogu-P3246 心路历程卡常历程问题存疑 一直在想莫队的做法。发现左右指针的移动对应一段左/右端点固定的子序列&#xff0c;然后可以一个数代表一段相同的贡献。 就开始求 lsti,nxtilst_i,nxt_ilsti​,nxti​ 了。 仔细想想需要找到 lstlsti<l≤lstilst_{lst_…

cf1523C. Compression and Expansion

cf1523C. Compression and Expansion 题意&#xff1a; 让你模拟出一个书的目录&#xff0c;对于每一行给你一个数字&#xff0c;表示这个目录的最后一个数&#xff0c; 题解&#xff1a; 我们用vector存当前的目录情况&#xff0c;读到下一行&#xff0c;在尽量少删上一行…

《从零开始学ASP.NET CORE MVC》:ASP.NET Core 中的 Main方法(5)

本文出自《从零开始学ASP.NET CORE MVC》推荐文章&#xff1a;ASP.NET Core Web 项目文件ASP.NET Core 中的 Main方法一个开始专心写字的人在ASP.NET Core项目中&#xff0c;我们有一个名为Program.cs的文件。在这个文件中&#xff0c;我们有一个public static void Main&#…

[HNOI2016] 大数(莫队)

problem luogu-P3245 solution 将这个 nnn 位数从右往左的记录取模 ppp 的结果&#xff0c;即 f(i)(f(i−1)∗10si)%pf(i)(f(i-1)*10s_i)\% pf(i)(f(i−1)∗10si​)%p。 显然一个子串是 ppp 的倍数必然满足&#xff1a;f(r)−f(l−1)10r−l1≡0(modp)\frac{f(r)-f(l-1)}{10…

2021牛客暑期多校训练营9

2021牛客暑期多校训练营9 题号题目知识点AA Math ChallengeBBest SubgraphCCellsDDivide-and-conquer on TreeEEyjafjallaFFinancial Order ExecutionGGlass BallsHHappy NumberIIncentive ModelJJam

.NET中的状态机库Stateless

标题&#xff1a;.NET中的状态机库Stateless 作者&#xff1a;Lamond Lu 地址&#xff1a;https://www.cnblogs.com/lwqlun/p/10674018.html[1]介绍什么是状态机和状态模式状态机是一种用来进行对象建模的工具&#xff0c;它是一个有向图形&#xff0c;由一组节点和一组相应的转…

[APIO2016] 划艇(dp + 组合数 + 前缀和优化)

problem luogu-P3643 solution 有个显然的暴力 dpdpdp。设 dp(i,j):dp(i,j):dp(i,j): 到了第 iii 个学校&#xff0c;其参加且派出 jjj 个划艇的方案数。 枚举上一个参加的学校以及派出的划艇&#xff0c;则有转移&#xff1a;dp(i,j)∑k<i,j<jdp(k,j′)dp(i,j)\sum_…

.net core webapi 前后端开发分离后的配置和部署

背景&#xff1a;现在越来越多的企业都采用了在开发上前后端分离&#xff0c;前后端开发上的分离有很多种&#xff0c;那么今天&#xff0c;我来分享一下项目中得的前后端分离。B/S Saas 项目&#xff1a;&#xff08;这个项目可以理解成个人中心&#xff0c;当然不止这么点功…

Happy Number

Happy Number 题意 &#xff1a; 开心数是由仅由2&#xff0c;3&#xff0c;6组成的&#xff0c;问第n个开心数是哪个&#xff1f; 1<n<1e9 题解&#xff1a; 正解应该是&#xff1a; 首先确定k大数有几位&#xff1a; 然后就知道k大数是x位下的第k’大的 把2看成0&a…

[HNOI2015] 接水果(倍增 + 整体二分)

problem luogu-P3242 solution 本题的难点在于如何判定路径之间是否覆盖。 这里我们尝试树常见的 dfs\text{dfs}dfs 序。 考虑 x−yx-yx−y 路径如果要覆盖 u−vu-vu−v 路径需要满足怎样的条件。 以下均假设 dfs(u)<dfs(v),dfs(x)<dfs(y)dfs(u)<dfs(v),dfs(x)&…

ASP.NET Core使用Jaeger实现分布式追踪

前言最近我们公司的部分.NET Core的项目接入了Jaeger&#xff0c;也算是稍微完善了一下.NET团队的技术栈。至于为什么选择Jaeger而不是Skywalking&#xff0c;这个问题我只能回答&#xff0c;大佬们说了算。前段时间也在CSharpCorner写过一篇类似的介绍Exploring Distributed T…

[SCOI2007] 修车(费用流 + 差分时间段建图)

problem luogu-P2053 solution 假设只有一个工作人员。修车顺序为 p1,p2,...,pnp_1,p_2,...,p_np1​,p2​,...,pn​ 是一个 nnn 的排列。 那么对于第 iii 个被修的车的等待时间应为 Tp1...TpiT_{p_1}...T_{p_i}Tp1​​...Tpi​​。 总的等待时间则是 Tp1(Tp1Tp2)...(Tp1..…