![Jenkins 2.x实践指南](https://wfqqreader-1252317822.image.myqcloud.com/cover/830/25449830/b_25449830.jpg)
5.2 单元测试
每种编程语言都有自己的单元测试框架。执行单元测试的工作一般由构建工具来完成。Jenk-ins做的只不过是执行这些构建工具的单元测试命令,然后对测试报告进行收集,并呈现。
Jenkins并不会自动帮我们写单元测试,写单元测试还是要靠人。为什么要这样说呢?因为笔者发现,不少人认为Jenkins的自动化测试是指Jenkins代替人自动写测试。
5.2.1 JUnit单元测试报告
JUnit是一个Java语言的单元测试框架,由Kent Beck和Erich Gamma创建。当执行maven test命令时,Maven会执行测试阶段(包括单元测试),然后生成测试报告。
收集并展示JUnit测试报告的步骤如下:
(1)安装Jenkins JUnit插件(https://plugins.jenkins.io/junit)。
(2)在Jenkins中加入junit步骤。通常将junit步骤放在post always中,因为当测试不通过时,我们依然可以收集到测试报告。写法如下:
![](https://epubservercos.yuewen.com/29EDEB/13898202705417506/epubprivate/OEBPS/Images/68_1.jpg?sign=1739273678-QlrZ64HFqQi4rZkcuk6RnhzBvI8BoepZ-0-0be12cb2f390e902cebfd7fccdf78afa)
当pipeline运行结束后,在构建页的左边菜单栏及右边详情下都会多出一个链接:Test Result,如图5-3所示。
![](https://epubservercos.yuewen.com/29EDEB/13898202705417506/epubprivate/OEBPS/Images/68_2.jpg?sign=1739273678-WNeGdYNGL5QBHm7wbuM5IlZhlpxFh6TV-0-f0e50e41e0a3cb80b1a8b595bef55d4c)
图5-3 JUnit测试结果报告链接
单击“Test Result”进入,可以看到测试报告的详细信息,如图5-4所示。
![](https://epubservercos.yuewen.com/29EDEB/13898202705417506/epubprivate/OEBPS/Images/68_3.jpg?sign=1739273678-afzrzJXzDcaH2GCjqe9mI5rmKPMul2m3-0-6073e2c736ae30d72d946e10acd485a9)
图5-4 JUnit测试报告详情
junit步骤的testResults参数支持Ant风格路径表达式。**/target/surefire-reports/*.xml表示只要是target/surefire-reports目录下的XML文件就会被当作JUnit测试报告处理,而不论target在哪个层级的目录下。
5.2.2 JaCoCo实现代码覆盖率
JUnit只是方便我们写单元测试的一个框架,但是并没有告诉我们有多少代码被测试覆盖到了。而JaCoCo填补了这一空白。JaCoCo是一个免费的Java代码覆盖率的库,能帮助我们检测出代码覆盖率,并输出覆盖率报告。
JaCoCo提供了以下几个维度的覆盖率分析。
• 指令覆盖率(Instruction Coverage)
• 分支覆盖率(Branch Coverage)
• 圈复杂度覆盖率(Cyclomatic Complexity Coverage)
• 行覆盖率(Line Coverage)
• 方法覆盖率(Method Coverage)
• 类覆盖率(Class Coverage)
以下是JaCoCo插件的使用步骤。
(1)安装JaCoCo插件(https://plugins.jenkins.io/jacoco)。
(2)在Maven项目中引入JaCoCo插件,执行maven jacoco生成代码覆盖率报告。
![](https://epubservercos.yuewen.com/29EDEB/13898202705417506/epubprivate/OEBPS/Images/69_1.jpg?sign=1739273678-TOqupwguI7qxoeu5JtIo55wVuTIuXNab-0-fbab2a1eb63dd2f9a90862e2da373937)
![](https://epubservercos.yuewen.com/29EDEB/13898202705417506/epubprivate/OEBPS/Images/70_1.jpg?sign=1739273678-T8xzJjzmQKTiqteTOn6ehqsQKBx7PyT7-0-ce9932de8c9defc5d93f8777f9f7ea28)
(3)使用jacoco步骤。jacoco步骤在mvn命令之后执行,写法如下:
![](https://epubservercos.yuewen.com/29EDEB/13898202705417506/epubprivate/OEBPS/Images/70_2.jpg?sign=1739273678-pI06WkfBPrF2nRbnMyjNsZeyVbPjTaE5-0-993e79bf1aa8c470c8abb9f4a1a0dafc)
![](https://epubservercos.yuewen.com/29EDEB/13898202705417506/epubprivate/OEBPS/Images/71_1.jpg?sign=1739273678-9a21U3GW731Bko2tUEtFe9zqf3dPkhiK-0-6dd68b0502e5bdb8182371620d7f8c77)
为了更好地理解 jacoco 步骤的参数,我们看看 JaCoCo 插件在自由风格项目中的 UI,如图5-5所示。
![](https://epubservercos.yuewen.com/29EDEB/13898202705417506/epubprivate/OEBPS/Images/71_2.jpg?sign=1739273678-stttdmNEbhlE64mBGXLfkShd4tkut3uv-0-f485ff32d89931486f6dccaa7a5f46db)
图5-5 jacoco步骤
pipeline运行完成后,我们可以在任务详情页的下方看到报告,如图5-6所示。
buildOverBuild和changeBuildStatus参数都能影响Jenkins任务的结果状态,那么当这两个参数的值都为true时,结果是什么呢?由其共同决定。以下是它们的判断逻辑。
![](https://epubservercos.yuewen.com/29EDEB/13898202705417506/epubprivate/OEBPS/Images/72_1.jpg?sign=1739273678-ryV6VQTwzcYFaRGaq8vDC30so2dAZyrN-0-96d17695472ce6feef3142bdc6f7145a)
![](https://epubservercos.yuewen.com/29EDEB/13898202705417506/epubprivate/OEBPS/Images/72_2.jpg?sign=1739273678-qpPzm9jS8HjNINr4olALBwhu3qlzbGsP-0-591899601a26db1b825900c928fdac9d)
图5-6 任务详情页呈现代码覆盖率
最后,各个维度的覆盖率应该设置多少呢?没有标准答案。
笔者的经验是先要确定项目是遗留的还是新建的。遗留的就以当前覆盖率为基线,新建的则设置相对高一些的要求。再看项目的紧急程度,如果非常紧急的话,则可以考虑放低要求。最后看项目的重要程度。如果这个项目在整个架构中起着非常重要的作用,那么覆盖率要求会高一些。
5.2.3 代码覆盖率越高,软件的质量就越高吗
代码覆盖率越高,软件的质量就越高吗?我们来看看《软件之道:软件开发争议问题剖析》中是怎么说的:
为了找到两者之间的关系,把Windows Vista(4000多万行代码、几千个二进制文件、数千名工程师)的分支覆盖率(Branch Coverage)与块覆盖率(Block Coverage)和其发布六个月内的现场缺陷对应起来。我们观察到覆盖率和质量之间有弱正相关性,预测查准率和查全率较差(查准率为83.8%,查全率为54.8%)。
书中最终给出的答案是:
代码覆盖率最好不要单独使用,而是需要与其他指标,如代码变动率、复杂度等一并考虑。
所以,如果考虑将代码覆盖率作为团队开发人员的KPI,请慎重。