Skip to content

Commit f4c2fa6

Browse files
committed
test(android, jacoco): add native coverage report, call it in e2e
- carefully try to terminate app - do not use `--cleanup` command line in E2E as it shuts down emulator before coverage fetch
1 parent fbab915 commit f4c2fa6

File tree

7 files changed

+168
-4
lines changed

7 files changed

+168
-4
lines changed

.github/workflows/tests_e2e_android.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,8 @@ jobs:
185185
$ANDROID_HOME/platform-tools/adb shell settings put global animator_duration_scale 0.0
186186
nohup sh -c "until false; do $ANDROID_HOME/platform-tools/adb shell input tap 100 800; sleep 0.2; done" &
187187
nohup sh -c "$ANDROID_HOME/platform-tools/adb logcat '*:D' > adb-log.txt" &
188-
yarn tests:android:test-cover --cleanup
188+
yarn tests:android:test-cover
189+
yarn tests:android:test:jacoco-report
189190
shell: bash
190191

191192
- name: Submit Coverage

.github/workflows/tests_e2e_ios.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ jobs:
162162
timeout-minutes: 40
163163
run: |
164164
cd tests
165-
./node_modules/.bin/nyc ./node_modules/.bin/detox test --debug-synchronization 200 --configuration ios.sim.debug --cleanup
165+
./node_modules/.bin/nyc ./node_modules/.bin/detox test --debug-synchronization 200 --configuration ios.sim.debug
166166
167167
- name: Upload Buildcache Log
168168
uses: actions/upload-artifact@v2

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
"tests:android:test-reuse": "cd tests && ./node_modules/.bin/detox test --configuration android.emu.debug --reuse",
3131
"tests:android:test-cover": "cd tests && ./node_modules/.bin/nyc ./node_modules/.bin/detox test --configuration android.emu.debug",
3232
"tests:android:test-cover-reuse": "cd tests && ./node_modules/.bin/nyc ./node_modules/.bin/detox test --configuration android.emu.debug --reuse",
33+
"tests:android:test:jacoco-report": "cd tests/android && ./gradlew jacocoAndroidTestReport",
3334
"tests:ios:build": "cd tests && ./node_modules/.bin/detox build --configuration ios.sim.debug",
3435
"tests:ios:build-release": "cd tests && ./node_modules/.bin/detox build --configuration ios.sim.release",
3536
"tests:ios:test": "cd tests && ./node_modules/.bin/detox test --configuration ios.sim.debug --loglevel warn",

tests/android/app/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ android {
112112
}
113113
}
114114

115+
apply from: './jacoco.gradle'
116+
115117
dependencies {
116118
implementation fileTree(include: ['*.jar'], dir: 'libs')
117119
//noinspection GradleDynamicVersion

tests/android/app/jacoco.gradle

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
import groovy.transform.Memoized
2+
3+
apply plugin: 'jacoco'
4+
5+
jacoco {
6+
toolVersion = '0.8.7'
7+
}
8+
9+
android {
10+
jacoco {
11+
version = '0.8.7'
12+
}
13+
}
14+
15+
@Memoized
16+
Properties getLocalProperties() {
17+
final propertiesFile = project.rootProject.file('local.properties')
18+
19+
final properties = new Properties()
20+
21+
if (propertiesFile.exists()) {
22+
properties.load(propertiesFile.newDataInputStream())
23+
}
24+
25+
return properties
26+
}
27+
28+
def openReport(htmlOutDir) {
29+
final reportPath = "$htmlOutDir/index.html"
30+
31+
println "HTML Report: $reportPath"
32+
33+
if (!project.hasProperty('open-report')) {
34+
println "to open the report automatically in your default browser add '-Popen-report' cli argument"
35+
return
36+
}
37+
38+
def os = org.gradle.internal.os.OperatingSystem.current()
39+
if (os.isWindows()) {
40+
exec { commandLine 'cmd', '/c', "start $reportPath" }
41+
} else if (os.isMacOsX()) {
42+
exec { commandLine 'open', "$reportPath" }
43+
} else if (os.isLinux()) {
44+
try {
45+
exec { commandLine 'xdg-open', "$reportPath" }
46+
} catch (Exception ignored) {
47+
if (localProperties.containsKey('linux-html-cmd')) {
48+
exec { commandLine properties.get('linux-html-cmd'), "$reportPath" }
49+
} else {
50+
println "'linux-html-cmd' property could not be found in 'local.properties'"
51+
}
52+
}
53+
}
54+
}
55+
56+
tasks.withType(Test) {
57+
jacoco.includeNoLocationClasses = true
58+
jacoco.excludes = ['jdk.internal.*']
59+
}
60+
61+
// Our merge report task
62+
task jacocoTestReport(type: JacocoReport, dependsOn: ['testDebugUnitTest', 'connectedDebugAndroidTest']) {
63+
def htmlOutDir = layout.buildDirectory.dir("reports/jacoco/$name/html").get().asFile
64+
65+
doLast {
66+
openReport htmlOutDir
67+
}
68+
69+
reports {
70+
xml.enabled = true
71+
html.destination htmlOutDir
72+
}
73+
74+
def fileFilter = ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*', '**/*Test*.*', 'android/**/*.*']
75+
def debugTree = fileTree(dir: "$project.buildDir/intermediates/javac/debug/classes", excludes: fileFilter)
76+
def debugTree2 = fileTree(dir: "$project.buildDir/../../node_modules/@react-native-firebase/android/build/intermediates/javac/debug/classes", excludes: fileFilter)
77+
def mainSrc = "$project.projectDir/src/main/java"
78+
def mainSrc2 = "$project.projectDir/../../node_modules/@react-native-firebase/android/src/main/java"
79+
80+
sourceDirectories.from = files([mainSrc, mainSrc2])
81+
classDirectories.from = files([debugTree, debugTree2])
82+
executionData.from = fileTree(dir: project.buildDir, includes: [
83+
'**/*.exec',
84+
'**/*.ec'
85+
])
86+
}
87+
88+
// A unit-test only report task
89+
task jacocoUnitTestReport(type: JacocoReport, dependsOn: ['testDebugUnitTest']) {
90+
def htmlOutDir = layout.buildDirectory.dir("reports/jacoco/$name/html").get().asFile
91+
92+
// Runs normal test but with this added:
93+
// -javaagent:build/tmp/expandedArchives/org.jacoco.agent-0.8.7.jar_3a83c50b4a016f281c4e9f3500d16b55/jacocoagent.jar=destfile=build/jacoco/testPlayDebugUnitTest.exec,append=true,excludes=jdk.internal.*,inclnolocationclasses=true,dumponexit=true,output=file,jmx=false
94+
95+
doLast {
96+
openReport htmlOutDir
97+
}
98+
99+
reports {
100+
xml.enabled = true
101+
html.destination htmlOutDir
102+
}
103+
104+
def fileFilter = ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*', '**/*Test*.*', 'android/**/*.*']
105+
def debugTree = fileTree(dir: "$project.buildDir/intermediates/javac/debug/classes", excludes: fileFilter)
106+
def mainSrc = "$project.projectDir/src/main/java"
107+
108+
sourceDirectories.from = files([mainSrc])
109+
classDirectories.from = files([debugTree])
110+
executionData.from = fileTree(dir: project.buildDir, includes: [
111+
'**/*.exec'
112+
113+
])
114+
}
115+
116+
// A connected android tests only report task
117+
task jacocoAndroidTestReport(type: JacocoReport) {
118+
def htmlOutDir = layout.buildDirectory.dir("reports/jacoco/$name/html").get().asFile
119+
120+
doLast {
121+
openReport htmlOutDir
122+
}
123+
124+
reports {
125+
xml.enabled = true
126+
html.destination htmlOutDir
127+
}
128+
129+
def fileFilter = ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*', '**/*Test*.*', 'android/**/*.*']
130+
131+
// use our collected firebase module names to aggregate source / class files for reporting
132+
def classFiles = []
133+
def srcFiles = []
134+
rootProject.ext.firebaseModulePaths.forEach { projectPath ->
135+
classFiles << fileTree(dir: "$projectPath/build/intermediates/javac/debug/classes", excludes: fileFilter)
136+
srcFiles << "$projectPath/src/main/java"
137+
}
138+
139+
140+
sourceDirectories.from = files(srcFiles)
141+
classDirectories.from = files(classFiles)
142+
executionData.from = fileTree(dir: project.buildDir, includes: [
143+
'**/*.ec'
144+
])
145+
}

tests/android/build.gradle

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ buildscript {
2323
ext.supportV4Version = "1.0.0" // https://developer.android.com/jetpack/androidx/releases/legacy androidx.legacy:legacy-support-v4
2424
ext.swiperefreshlayoutVersion = "1.1.0" // https://developer.android.com/jetpack/androidx/releases/swiperefreshlayout
2525

26+
// used to aggregate all modules for later reporting
27+
ext.firebaseModulePaths = []
28+
2629
repositories {
2730
google()
2831
mavenCentral()
@@ -59,15 +62,23 @@ allprojects {
5962
}
6063
}
6164

65+
// collect all our modules for reporting
66+
subprojects.forEach { project ->
67+
if (project.name.contains("react-native-firebase")) {
68+
rootProject.ext.firebaseModulePaths << project.projectDir
69+
}
70+
}
71+
6272
subprojects {
6373
task listAllDependencies(type: DependencyReportTask) {}
74+
75+
// Force all subprojects to use one and only one set of versions
6476
ext {
6577
compileSdk = rootProject.ext.compileSdkVersion
6678
buildTools = rootProject.ext.buildToolsVersion
6779
minSdk = rootProject.ext.minSdkVersion
6880
targetSdk = rootProject.ext.targetSdkVersion
6981
}
70-
7182
afterEvaluate { project ->
7283
if (!project.name.equalsIgnoreCase("app")
7384
&& project.hasProperty("android")) {

tests/e2e/init.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,5 +76,9 @@ after(async function () {
7676
}
7777
}
7878

79-
await device.terminateApp();
79+
try {
80+
await device.terminateApp();
81+
} catch (e) {
82+
console.log('Unable to terminate app?', e);
83+
}
8084
});

0 commit comments

Comments
 (0)