Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document coverage with orchestrator #482

Merged
merged 3 commits into from
Feb 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,113 @@ flank:
- .*\.mp4$
```

### Android code coverage

<details>
<summary>Update your app's build.gradle to build with coverage and use orchestrator.
A custom gradle task is defined to generate the coverage report.</summary>

```gradle
def coverageEnabled = project.hasProperty('coverage')

android {

defaultConfig {
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
// runs pm clear after each test invocation
testInstrumentationRunnerArguments clearPackageData: 'true'
}

buildTypes {
debug {
testCoverageEnabled true
}
}

// https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.TestOptions.html#com.android.build.gradle.internal.dsl.TestOptions:animationsDisabled
testOptions {
execution 'ANDROIDX_TEST_ORCHESTRATOR'
animationsDisabled = true
}
}

dependencies {
androidTestUtil 'androidx.test:orchestrator:1.1.1'

androidTestImplementation("androidx.test:runner:1.1.1")
androidTestImplementation("androidx.test.ext:junit:1.1.0")
androidTestImplementation("androidx.test.ext:junit-ktx:1.1.0")
androidTestImplementation("androidx.test.ext:truth:1.1.0")
androidTestImplementation("androidx.test.espresso.idling:idling-concurrent:3.1.1")
androidTestImplementation("androidx.test.espresso.idling:idling-net:3.1.1")
androidTestImplementation("androidx.test.espresso:espresso-accessibility:3.1.1")
androidTestImplementation("androidx.test:rules:1.1.1")
androidTestImplementation("androidx.test.espresso:espresso-core:3.1.1")
androidTestImplementation("androidx.test.espresso:espresso-contrib:3.1.1")
androidTestImplementation("androidx.test.espresso:espresso-idling-resource:3.1.1")
androidTestImplementation("androidx.test.espresso:espresso-intents:3.1.1")
androidTestImplementation("androidx.test.espresso:espresso-web:3.1.1")
}

if (coverageEnabled) {
// gradle -Pcoverage firebaseJacoco
task firebaseJacoco(type: JacocoReport) {
group = "Reporting"
description = "Generate Jacoco coverage reports for Firebase test lab."

def excludes = [
'**/R.class',
'**/R$*.class',
'**/BuildConfig.*',
"**/androidx"]
def javaClasses = fileTree(dir: "${project.buildDir}/intermediates/javac/debug/compileDebugJavaWithJavac/classes", excludes: excludes)
def kotlinClasses = fileTree(dir: "${project.buildDir}/tmp/kotlin-classes/debug", excludes: excludes)
getClassDirectories().setFrom(files([javaClasses, kotlinClasses]))

getSourceDirectories().setFrom(files([
'src/main/java', 'src/main/kotlin',
'src/androidTest/java', 'src/androidTest/kotlin']))

def ecFiles = project.fileTree(dir: '..', include: 'results/coverage_ec/**/sdcard/*.ec')
ecFiles.forEach { println("Reading in $it") }
getExecutionData().setFrom(ecFiles)

reports {
html { enabled true }
xml { enabled false }
}
}
}
```

Here's an example flank.yml. Note that `coverage` and `coverageFilePath` must be set when using orchestrator with coverage.
`coverageFile` is not used. Orchestrator will generate one coverage file per test. `coverageFilePath` must be a directory, not a file.

```yaml
gcloud:
app: ./app/build/outputs/apk/debug/app-debug.apk
test: ./app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk
environment-variables:
coverage: true
coverageFilePath: /sdcard/
clearPackageData: true
directories-to-pull:
- /sdcard/
# use a named results dir that's used by the gradle task
results-dir: coverage_ec

flank:
disableSharding: true
files-to-download:
- .*/sdcard/[^/]+\.ec$
```

- Build the app with coverage: `./gradlew -Pcoverage build`
- Run flank `flank android run`
- Generate the report `./gradlew -Pcoverage firebaseJacoco`
- Open the report in `./build/reports/jacoco/firebaseJacoco/html/index.html`
</details>

### CI integration

Download Flank from GitHub releases.
Expand Down
7 changes: 6 additions & 1 deletion test_app/.gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
results/
91 changes: 91 additions & 0 deletions test_app/app/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'jacoco'

def coverageEnabled = project.hasProperty('coverage')

android {
compileSdkVersion 28
defaultConfig {
applicationId "com.example.test_app"
minSdkVersion 26
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
testInstrumentationRunnerArguments(clearPackageData: 'true')

}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}

debug {
testCoverageEnabled coverageEnabled
}
}

testOptions {
animationsDisabled = true
execution = "ANDROIDX_TEST_ORCHESTRATOR"
}
}

dependencies {
implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0-alpha01'
implementation 'androidx.core:core-ktx:1.1.0-alpha03'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'

// Espresso.
// https://developer.android.com/jetpack/androidx/releases/test
androidTestUtil 'androidx.test:orchestrator:1.1.1'

androidTestImplementation("androidx.test:runner:1.1.1")
androidTestImplementation("androidx.test.ext:junit:1.1.0")
androidTestImplementation("androidx.test.ext:junit-ktx:1.1.0")
androidTestImplementation("androidx.test.ext:truth:1.1.0")
androidTestImplementation("androidx.test.espresso.idling:idling-concurrent:3.1.1")
androidTestImplementation("androidx.test.espresso.idling:idling-net:3.1.1")
androidTestImplementation("androidx.test.espresso:espresso-accessibility:3.1.1")
androidTestImplementation("androidx.test:rules:1.1.1")
androidTestImplementation("androidx.test.espresso:espresso-core:3.1.1")
androidTestImplementation("androidx.test.espresso:espresso-contrib:3.1.1")
androidTestImplementation("androidx.test.espresso:espresso-idling-resource:3.1.1")
androidTestImplementation("androidx.test.espresso:espresso-intents:3.1.1")
androidTestImplementation("androidx.test.espresso:espresso-web:3.1.1")
}

if (coverageEnabled) {
// gradle -Pcoverage firebaseJacoco
task firebaseJacoco(type: JacocoReport) {
group = "Reporting"
description = "Generate Jacoco coverage reports for Firebase test lab."

def excludes = [
'**/R.class',
'**/R$*.class',
'**/BuildConfig.*',
"**/androidx"]
def javaClasses = fileTree(dir: "${project.buildDir}/intermediates/javac/debug/compileDebugJavaWithJavac/classes", excludes: excludes)
def kotlinClasses = fileTree(dir: "${project.buildDir}/tmp/kotlin-classes/debug", excludes: excludes)
getClassDirectories().setFrom(files([javaClasses, kotlinClasses]))

getSourceDirectories().setFrom(files([
'src/main/java', 'src/main/kotlin',
'src/androidTest/java', 'src/androidTest/kotlin']))

def ecFiles = project.fileTree(dir: '..', include: 'results/coverage_ec/**/sdcard/*.ec')
ecFiles.forEach { println("Reading in $it") }
getExecutionData().setFrom(ecFiles)

reports {
html { enabled true }
xml { enabled false }
}
}
}
44 changes: 0 additions & 44 deletions test_app/app/build.gradle.kts

This file was deleted.

21 changes: 21 additions & 0 deletions test_app/app/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

This file was deleted.

Loading