草帽路飞UU 发表于 2022-8-3 15:15:33

Java 服务端和 Android 端手工测试覆盖率统计的实现(上)

本帖最后由 草帽路飞UU 于 2022-8-10 16:54 编辑

 一、前言
  代码测试覆盖率工具流行了这么多年,已经有很多成熟方案比如 Jacoco,我司近一段时间开始了这方面的摸索,很荣幸这个任务到了我的手里,于是乎就开始踩坑之旅。
  之前已经搞定了 Java 后端的覆盖率统计,由于我们没有 UT,毫无疑问使用的还是 On-the-fly 模式,最近几天开始了 App 端的手工测试覆盖率统计之旅,中间出现了一些坑,有的很快就搞定了,有的也多多少少占用了不少时间,在此记录一下,抛砖引玉,大家一起探讨。
  二、思路整理
  2.1 关于 Java 端
  我们都知道,Jacoco 流行了这么多年,无疑是解决 Java 后端覆盖率的不二之选 (至于 Emma,当然也是先驱,只不过我们没有选择)。分析了我司关于 Java 端项目的现状,总结了如下几点:
  · 老牌的项目,使用 Java6, 框架就是 ssh ,一般来说都是 Ant 构建,jetty 部署。
  · 稍微新一点的项目,使用 Java8,主框架 SSM,一般直接 maven 构建,maven 的 tomcat 插件部署或者打成 war 包用 tomcat 部署。
  · 再新一点的项目,使用 Java8,就是 Springboot 和 Spring Cloud 框架,maven 的 springboot 插件部署或者 war 包用 tomcat 部署,或者打成 jar 包,直接用 Java 命令启动。
  终其一点,还是要用 On-the-fly 模式,方便。
  2.2 关于Android 端
  基本清一色 Android Studio 开发,gradle 构建打包。
  2.3 关于覆盖率环境的部署和收集
  研究过 Jacoco 的都知道,它支持多种方式的部署和报告生成。但总结到一点,还是修改启动时候的 JVM 参数,-Javaagent 配置一下,但是不同的构建工具有其封装方式,Ant 和 Maven 也是 shell或者 bat 脚本,对一系列操作的封装,底层依然是 Java 命令的调用。
  所以一个万能的方式,就是修改 Ant 和 mvn 的脚本,直接修改其脚本中用到的 JAVA_OPTS 参数,但是弊端也很明显,就是会对所有的 Ant 和 mvn 命令生效,因此并不可取。
  所以,还是选择了针对特定构建和打包方式的启动适配。
  比如:
  ·Ant 启动
  可以修改 build.xml,在启动部署的 target(比如我司是用 startJetty) 中配置一个 jvmarg,设置成需要启动的 Jacoco 配置,如下所示:<target name="startJetty">
      <mkdir dir="../logs" />
      <mkdir dir="../heapdump" />
      <java classname="com.tianque.JettyProduction" spawn="true" classpath="${classes.dir}" classpathref="all.lib" fork="true">
        <arg value="${port}" />
        <arg value="${listenerport}" />
        <arg value="${path}" />
        <arg value="${rootdir}" />
        <arg value="${openJob}" />
        <jvmarg value="-Javaagent:/home/admin/Jacocoagent/Jacocoagent.jar=includes=*,output=tcpserver,port=8888,address=192.168.1.105" /> ·Maven 启动
  mvn 启动的时候,看过 mvn 脚本的大概知道,他提供了一个 MAVEN_OPTS 这个环境变量,可以临时修改启动参数,因此对 mvn tomcat7:run 或者 mvn springboot:run 这种方式部署项目,可以选择临时修改它,来完成 Jacoco 的注入,如下所示:
export MAVEN_OPTS="-Javaagent:JacocoJarPath=includes=*,output=tcpserver,port=2014,address=192.168.110.1"
之后,在运行 mvn xx:run(需要后台启动的话,加上 nohup 也无可厚非),这样基本可以注入 Jacoco agent 了。
  部署之后,再设置:
  export MAVEN_OPTS=""
就可以恢复,或者换个 terminal 窗口,也可以恢复,这样不用动任何的后端代码,也不会对当前的服务器环境造成污染,开发在测试环境部署的时候,有很多会喜欢这种方式。
  · jar 启动 Ant
  这个就更简单了,因为这个是最原始也是直接的 Java 应用启动方式。
 Java -Javaagent: $JacocoJarPath=includes=*,output=tcpserver,port=2014,address=192.168.110.1 -jarxxxxxxxxxx.jar
此处需要注意-Javaagent 这个参数的放置位置,因为放在 .jar 包之前是针对 jvm 设置,放到 .jar 之后是针对 jar 包里启动的 main 方法 args 的参数,位置放错,就会注入 Jacoco 失败。
  · tomcat 启动
  这种方式,就是改变 tomcat 的启动文件,catalina.sh 或者 catalina.bat 中的 JAVA_OPTS 参数,这个网上文档有很多,不再多说。
  2.4 关于覆盖率数据的收集和报告生成
  这也有很多方式,比如用 Ant 的 build.xml 和 maven 的 Jacoco 插件来收集和生成报告,这个网上也有很多,不再多议。
  但其实看过官方文档的就知道,其实 Jacoco 自己提供了 API,来收集和生成报告,这是比较原始的方式,也是最好用的方式。
  Jacoco 给出的 API 示例如下:
  Jacoco 官方的 API 示例地址:
  https://www.Jacoco.org/Jacoco/trunk/doc/API.html
  为了降低测试部对这些知识的学习成本,我选择了统一的方式,用 API 来收集和生成报告,这样以来,测试人员需要介入的地方就只剩下了带有 Jacoco agent 的测试环境部署,剩余的事情,交给我就行了。
  因此,花了点时间做了个覆盖率的收集和生成报告的平台,这个后面会简单说下,不是为了炫耀也不是为了拿绩效,就是单纯想减少学习成本 (这样大家就不会抱怨还要学习 Ant 的知识啦、maven 的知识啦、可能还需要学习 Java 的知识啦,虽然这是好的,但是我相信还是有很多人不愿意投入的)。
  2.5 关于 App 端覆盖率的收集和报告生成
  关于 App 端的覆盖率收集和报告生成,社区有很多帖子介绍,我稍后也会提到,给我帮助很多。
  主要思路,就是先拿到手工测试的覆盖率数据,因为这里是用 offline 的方式生成的,这一点好像途径并不多,但比较麻烦,还是要懂 Android 端的开发知识 (比如 AS 的使用、gradle 的配置和任务执行、Android 工程代码的结构、甚至还要懂一些 Groovy 的语法等等),因为要涉及到对工程的一部分修改和打包。
  拿到覆盖率数据之后,就可以生成报告了,那按照之前的说法,也有两种方式:
  · 使用 Gradle 的 Jacoco plugin,它给出了生成报告的任务,这些可以看参考资料。
  · 有了前面的覆盖率收集和报告生成平台,既然收集不需要了,那么报告生成是可以复用的嘛,于是乎做了下对 Gradle 工程的适配,只要上传 App 端的 exec 文件,就可以生成报告。
  我选择了后者,还是那句话,因为如果用前者,那势必要给测试人员讲解 Android 开发一些相关知识 (生成报告的时候,还要涉及到源码和 class 文件的配置,以及涉及到多模块的收集配置)
  四、App 端覆盖率进行时遇到的坑
  按照上述的这些精彩文章里,对 Android 端的代码覆盖率统计的介绍里,照理来说应当一气呵成了,但还是遇到了一些坑。
  比如: 在收集到手机端的覆盖率数据之后,传到后台,开始生成的时候,一直报以下错误:
c.a.p.t.j.ReportGenerator - IO 异常 ,Cannot read execution data version 0x1006. This version of Jacoco uses execution data version 0x1007.
   c.a.p.e.GlobalExceptionHandler -
  com.administrator.platform.exception.base.BusinessValidationException: 覆盖率的 Jacoco 版本不匹配:Cannot read execution data version 0x1006. This version of Jacoco uses execution data version 0x1007.
经过分析,这是覆盖率数据和当前所用生成报告的 Jacoco 版本不一致,我用的是 0.8.1-snapshort 版本,它支持的版本是 0X1007,这个从 Jacoco 的源码可以看到:

很显然,是 App 端生成的覆盖率数据版本低了。
  可是按照上面的文档,Jacoco 中的 toolVersion 已经设置成 0.8.1 了啊,它肯定支持的也是 0X1007 啊。
  而且查了官方给出的文档,对应关系如下:

GitHub 地址在:
  https://github.com/Jacoco/Jacoco/wiki/ExecFileVersions










页: [1]
查看完整版本: Java 服务端和 Android 端手工测试覆盖率统计的实现(上)