splitting unit and instrumentation test tasks so that we can configure the android plugin testCoverage parameter

- there's a bug that causes the output to be invalid for unit tests
This commit is contained in:
Adam Brown 2022-06-14 15:56:16 +01:00
parent b5aedd4626
commit a76b6e522b
5 changed files with 41 additions and 23 deletions

View file

@ -49,7 +49,10 @@ jobs:
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: true disable-animations: true
emulator-build: 7425822 emulator-build: 7425822
script: ./gradlew theCodeCoverageReport -Pandroid.testInstrumentationRunnerArguments.notPackage=im.vector.app.ui --stacktrace $CI_GRADLE_ARG_PROPERTIES script: |
./gradlew unitTestsWithCoverage --stacktrace $CI_GRADLE_ARG_PROPERTIES
./gradlew instrumentationTestsWithCoverage -Pandroid.testInstrumentationRunnerArguments.notPackage=im.vector.app.ui --stacktrace $CI_GRADLE_ARG_PROPERTIES
./gradlew generateCoverageReport --stacktrace $CI_GRADLE_ARG_PROPERTIES
# NB: continue-on-error marks steps.tests.conclusion = 'success' but leaves stes.tests.outcome = 'failure' # NB: continue-on-error marks steps.tests.conclusion = 'success' but leaves stes.tests.outcome = 'failure'
- name: Run all the codecoverage tests at once (retry if emulator failed) - name: Run all the codecoverage tests at once (retry if emulator failed)
uses: reactivecircus/android-emulator-runner@v2 uses: reactivecircus/android-emulator-runner@v2
@ -62,7 +65,10 @@ jobs:
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: true disable-animations: true
emulator-build: 7425822 emulator-build: 7425822
script: ./gradlew theCodeCoverageReport -Pandroid.testInstrumentationRunnerArguments.notPackage=im.vector.app.ui --stacktrace $CI_GRADLE_ARG_PROPERTIES script: |
./gradlew unitTestsWithCoverage --stacktrace $CI_GRADLE_ARG_PROPERTIES
./gradlew instrumentationTestsWithCoverage -Pandroid.testInstrumentationRunnerArguments.notPackage=im.vector.app.ui --stacktrace $CI_GRADLE_ARG_PROPERTIES
./gradlew generateCoverageReport --stacktrace $CI_GRADLE_ARG_PROPERTIES
- run: ./gradlew sonarqube $CI_GRADLE_ARG_PROPERTIES - run: ./gradlew sonarqube $CI_GRADLE_ARG_PROPERTIES
if: always() # we may have failed a previous step and retried, that's OK if: always() # we may have failed a previous step and retried, that's OK
env: env:

View file

@ -168,7 +168,7 @@ def launchTask = getGradle()
.toString() .toString()
.toLowerCase() .toLowerCase()
if (launchTask.contains("codeCoverageReport".toLowerCase())) { if (launchTask.contains("coverage".toLowerCase())) {
apply from: 'coverage.gradle' apply from: 'coverage.gradle'
} }
@ -191,7 +191,7 @@ sonarqube {
property "sonar.links.issue", "https://github.com/vector-im/element-android/issues" property "sonar.links.issue", "https://github.com/vector-im/element-android/issues"
property "sonar.organization", "new_vector_ltd_organization" property "sonar.organization", "new_vector_ltd_organization"
property "sonar.java.coveragePlugin", "jacoco" property "sonar.java.coveragePlugin", "jacoco"
property "sonar.coverage.jacoco.xmlReportPaths", "${project.buildDir}/reports/jacoco/theCodeCoverageReport/theCodeCoverageReport.xml" property "sonar.coverage.jacoco.xmlReportPaths", "${project.buildDir}/reports/jacoco/generateCoverageReport/generateCoverageReport.xml"
property "sonar.login", project.hasProperty("SONAR_LOGIN") ? SONAR_LOGIN : "invalid" property "sonar.login", project.hasProperty("SONAR_LOGIN") ? SONAR_LOGIN : "invalid"
} }
} }

View file

@ -27,7 +27,7 @@ def initializeReport(report, projects, classExcludes) {
report.executionData { report.executionData {
fileTree(rootProject.rootDir.absolutePath).include( fileTree(rootProject.rootDir.absolutePath).include(
"**/build/outputs/unit_test_code_coverage/**/*.exec", "**/build/**/*.exec",
"**/build/outputs/code_coverage/**/coverage.ec", "**/build/outputs/code_coverage/**/coverage.ec",
) )
} }
@ -45,13 +45,11 @@ def initializeReport(report, projects, classExcludes) {
switch (project) { switch (project) {
case { project.plugins.hasPlugin("com.android.application") }: case { project.plugins.hasPlugin("com.android.application") }:
androidClassDirs.add("${project.buildDir}/tmp/kotlin-classes/gplayDebug") androidClassDirs.add("${project.buildDir}/tmp/kotlin-classes/gplayDebug")
androidSourceDirs.add("${project.buildDir}/generated/source/kapt/gplayDebug")
androidSourceDirs.add("${project.projectDir}/src/main/kotlin") androidSourceDirs.add("${project.projectDir}/src/main/kotlin")
androidSourceDirs.add("${project.projectDir}/src/main/java") androidSourceDirs.add("${project.projectDir}/src/main/java")
break break
case { project.plugins.hasPlugin("com.android.library") }: case { project.plugins.hasPlugin("com.android.library") }:
androidClassDirs.add("${project.buildDir}/tmp/kotlin-classes/debug") androidClassDirs.add("${project.buildDir}/tmp/kotlin-classes/debug")
androidSourceDirs.add("${project.buildDir}/generated/source/kapt/debug")
androidSourceDirs.add("${project.projectDir}/src/main/kotlin") androidSourceDirs.add("${project.projectDir}/src/main/kotlin")
androidSourceDirs.add("${project.projectDir}/src/main/java") androidSourceDirs.add("${project.projectDir}/src/main/java")
break break
@ -72,18 +70,20 @@ def collectProjects(predicate) {
return subprojects.findAll { it.buildFile.isFile() && predicate(it) } return subprojects.findAll { it.buildFile.isFile() && predicate(it) }
} }
task theCodeCoverageReport(type: JacocoReport) { task generateCoverageReport(type: JacocoReport) {
outputs.upToDateWhen { false } outputs.upToDateWhen { false }
rootProject.apply plugin: 'jacoco' rootProject.apply plugin: 'jacoco'
tasks.withType(Test) { def projects = collectProjects { ['vector', 'matrix-sdk-android'].contains(it.name) }
jacoco.includeNoLocationClasses = true
}
def projects = collectProjects { ['vector','matrix-sdk-android'].contains(it.name) }
dependsOn {
[':vector:testGplayDebugUnitTest'] +
[':vector:connectedGplayDebugAndroidTest'] +
[':matrix-sdk-android:testDebugUnitTest'] +
[':matrix-sdk-android:connectedDebugAndroidTest']
}
initializeReport(it, projects, excludes) initializeReport(it, projects, excludes)
} }
task unitTestsWithCoverage(type: GradleBuild) {
// the 7.1.3 android gradle plugin has a bug where enableTestCoverage generates invalid coverage
startParameter.projectProperties.coverage = [enableTestCoverage: false]
tasks = [':vector:testGplayDebugUnitTest', ':matrix-sdk-android:testDebugUnitTest']
}
task instrumentationTestsWithCoverage(type: GradleBuild) {
startParameter.projectProperties.coverage = [enableTestCoverage: true]
tasks = [':vector:connectedGplayDebugAndroidTest', 'matrix-sdk-android:connectedDebugAndroidTest']
}

View file

@ -5,6 +5,10 @@ apply plugin: 'kotlin-parcelize'
apply plugin: 'realm-android' apply plugin: 'realm-android'
apply plugin: "org.jetbrains.dokka" apply plugin: "org.jetbrains.dokka"
if (project.hasProperty("coverage")) {
apply plugin: 'jacoco'
}
buildscript { buildscript {
repositories { repositories {
// Do not use `mavenCentral()`, it prevents Dependabot from working properly // Do not use `mavenCentral()`, it prevents Dependabot from working properly
@ -74,7 +78,10 @@ android {
buildTypes { buildTypes {
debug { debug {
testCoverageEnabled true if (project.hasProperty("coverage")) {
println(coverage)
testCoverageEnabled = coverage.enableTestCoverage
}
// Set to true to log privacy or sensible data, such as token // Set to true to log privacy or sensible data, such as token
buildConfigField "boolean", "LOG_PRIVATE_DATA", project.property("vector.debugPrivateData") buildConfigField "boolean", "LOG_PRIVATE_DATA", project.property("vector.debugPrivateData")
// Set to BODY instead of NONE to enable logging // Set to BODY instead of NONE to enable logging

View file

@ -9,6 +9,10 @@ apply plugin: 'com.likethesalad.stem'
apply plugin: 'dagger.hilt.android.plugin' apply plugin: 'dagger.hilt.android.plugin'
apply plugin: 'kotlinx-knit' apply plugin: 'kotlinx-knit'
if (project.hasProperty("coverage")) {
apply plugin: 'jacoco'
}
kapt { kapt {
correctErrorTypes = true correctErrorTypes = true
} }
@ -119,8 +123,6 @@ ext.abiVersionCodes = ["armeabi-v7a": 1, "arm64-v8a": 2, "x86": 3, "x86_64": 4].
def buildNumber = System.env.BUILDKITE_BUILD_NUMBER as Integer ?: 0 def buildNumber = System.env.BUILDKITE_BUILD_NUMBER as Integer ?: 0
android { android {
// Due to a bug introduced in Android gradle plugin 3.6.0, we have to specify the ndk version to use // Due to a bug introduced in Android gradle plugin 3.6.0, we have to specify the ndk version to use
// Ref: https://issuetracker.google.com/issues/144111441 // Ref: https://issuetracker.google.com/issues/144111441
ndkVersion "21.3.6528147" ndkVersion "21.3.6528147"
@ -145,7 +147,7 @@ android {
versionName "${versionMajor}.${versionMinor}.${versionPatch}-sonar" versionName "${versionMajor}.${versionMinor}.${versionPatch}-sonar"
// Generate a random app task affinity // Generate a random app task affinity
manifestPlaceholders = [appTaskAffinitySuffix:"H_${gitRevision()}"] manifestPlaceholders = [appTaskAffinitySuffix: "H_${gitRevision()}"]
buildConfigField "String", "GIT_REVISION", "\"${gitRevision()}\"" buildConfigField "String", "GIT_REVISION", "\"${gitRevision()}\""
buildConfigField "String", "GIT_REVISION_DATE", "\"${gitRevisionDate()}\"" buildConfigField "String", "GIT_REVISION_DATE", "\"${gitRevisionDate()}\""
@ -244,7 +246,10 @@ android {
buildConfigField "boolean", "ENABLE_STRICT_MODE_LOGS", "false" buildConfigField "boolean", "ENABLE_STRICT_MODE_LOGS", "false"
signingConfig signingConfigs.debug signingConfig signingConfigs.debug
testCoverageEnabled true
if (project.hasProperty("coverage")) {
testCoverageEnabled = coverage.enableTestCoverage
}
} }
release { release {