Android 单元测试上传Sonarqube

前言

我们的测试用聚焦在应用程序的业务逻辑上,凭经验来说一个好的单元测试应该有如下测试分布:

70-80 % 是单元测试,保证基础代码功能的稳定

20-30 % 功能性测试,保证我们的应用程序可以运行

如果我们继承了其他应用组件的话,还需一部分交叉功能测试。

Android测试分类

Android测试分为本地测试(Local Unit Tests)和仪器测试(Instrumented Tests):

本地测试:

运行速度快;

无需连接Android真机或者模拟器;

对应目录是src/test/目录;

生成的报告文件是*.exec;

可视化查看报告目录:可在Android studio自带的coverage侧边栏插件更直观的查看。

仪器测试:

运行速度慢;

需要连接Android真机或者模拟器;

对应目录是src/androidTest/目录;

生成的报告文件是*.ec;

可视化查看报告目录:YOUR_PROJECT_PATH\app\build\reports\coverage\debug\index.html

测试报告生成
由于仪器测试运行速度慢,需要连接设备等不便因素影响,暂时只提供本地测试对接sonar配置。

希望Sonar上体现测试覆盖率时,则需将生成的报告文件提交到sonar。

第一步 修改工程根目录下build.gradle文件

这里用的jacoco插件用的是vanniktech提供的jacoco,另外gradle默认支持的是EclEmma提供的jacoco插件。

之所以不选用gradle默认的jacoco插件,是因为其不支持productFlavors配置,而vanniktech修复了该Bug。

vanniktech支持productFlavors修复反馈

Gradle Jacoco Plugin By Vanniktech

Gradle Jacoco Plugin By Default

buildscript {
  repositories {
    maven {
      url "https://plugins.gradle.org/m2/"
    }
  }
  dependencies {
    classpath "gradle.plugin.com.vanniktech:gradle-android-junit-jacoco-plugin:0.13.0"
  }
}

apply plugin: "com.vanniktech.android.junit.jacoco"
apply from: 'sonarqube.gradle'//create new sonar config.

第二步 创建sonarqube.gradle

这里创建sonarqube.gradle,一方面统一并完善sonar配置,一方面添加测试报告关联配置。

创建sonarqube.gradle于工程根目录下,

apply plugin: "org.sonarqube"

ext {
    SONAR_HOST = "http://...sonar-server-url...:9000/"
}

sonarqube {
    properties {
        property "sonar.host.url", SONAR_HOST
		//projectName根据QA要求命名
        property "sonar.projectName", "longfor-xxx"
		//projectKey建议使用项目的applicationId,注意相同的projectName,但不同的projectKey将在sonarqube上生成两个不同的项目!
        property "sonar.projectKey", rootProject.ext.applicationId
        property "sonar.sourceEncoding", "UTF-8"
        //Excluding src/androidTest/** and src/test/** is not allowed!
		//exclusions可以配置多个,以逗号分割
        property "sonar.exclusions", "src/main/res/**"

        property "sonar.sources", "src/main/"
        property "sonar.tests", "src/test/"
		//本地测试(Local Unit Tests)报告上传配置,注意sonar.jacoco.reportPath已弃用,使用sonar.jacoco.reportPaths.
        property "sonar.jacoco.reportPaths", fileTree(dir: project.projectDir, includes: ['**/*.exec'])
		//Instrumented Tests报告上传,目前未做上传
//        property "sonar.jacoco.itReportPath", fileTree(dir: project.projectDir, includes: ['**/*.ec'])
    }
}


//针对项目中其他Library Module进行单独配置
project(":base") {
    sonarqube {
		//不扫描该Module
        skipProject = true
    }
}


project(":biz") {
    sonarqube {
        properties {
			//不扫描该Module下的指定目录
            property "sonar.exclusions", "build/**," +
                    "src/main/res/**," +
                    "src/main/java/db/**"
        }
    }
}

第三步 修改主模块(Application Module)目录下build.gradle

Application Module即为build.gradle中声明

apply plugin: 'com.android.application'
的Module。

在其build.gradle中 添加 本地单元测试插件:

dependencies {
    ...此处省略其他包依赖
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
	...此处省略其他包依赖
}

第四步 运行上传命令

//将buildType为debug环境下的扫描报告上传sonar。注意指令顺序!!!
gradle jacocoTestReportDebug sonarqube --stacktrace

注意:

gradle 语句: 该命令因电脑系统mac/window,本地有无特殊配置而不同,其他写法有:./gradle ./gradlew等
jacocoTestReportDebug 语句: 该语句语法为jacocoTestReport,
即,在没有配置productFlavors的项目中只有jacocoTestReportDebug和jacocoTestReportRelease,
如果在productFlavors中配置了dev和uat,那么将会有:jacocoTestReportdevDebug,jacocoTestReportuatDebug,jacocoTestReportdevRelease,jacocoTestReportuatRelease.
sonarqube 语句: 上传到sonarqube.
–stacktrace 语句: 用于打印出生成测试报告,上传soanrqube过程中的报错信息,可写可不写。

本地单元测试代码示例
src/main/源代码:

public class StringUtils {
    private StringUtils() {
    }

    public static boolean isNull(String s) {
       return null == s || s.trim().length() <= 0;
    }

    public static boolean canParseInt(String s) {
        try {
            Integer.parseInt(s);
            return true;
        } catch (Exception e) {

        }
        return false;
    }
}

src/test/源代码:

public class StringUtilsTest {
    private String canParseInt_Value;

    @Before
    public void setUp() throws Exception {
        canParseInt_Value = "6";
    }

    @After
    public void tearDown() throws Exception {
    }

    @Test
    public void isNull() {
        assertThat(StringUtils.isNull(""), is(true));
        assertThat(StringUtils.isNull(null), is(true));
        assertThat(StringUtils.isNull("ab"), is(false));
    }

    @Test
    public void canParseInt() {
        assertThat(StringUtils.canParseInt(canParseInt_Value), is(true));
        assertThat(StringUtils.canParseInt("a"), is(false));
    }
}

注意事项

1、sonar配置中,相同的projectName,但不同的projectKey将在sonarqube上生成两个不同的项目!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值