Skip to content

Commit 712115b

Browse files
authored
Tests/android UI tests (#2013)
added new modules under the folder sentry-android-integration-tests - sentry-uitest-android: module for e2e tests, with a mock relay server with envelope and items assertions - sentry-uitest-android-benchmark: module for benchmarks, depends on sentry-uitest-android fix typo in Hub transactionListener -> transactionProfiler moved "androidx.test.runner.AndroidJUnitRunner" in Config.TestLibs.androidJUnitRunner added assertEnvelopeItem to assertions.kt
1 parent 77fd2f2 commit 712115b

File tree

34 files changed

+1442
-11
lines changed

34 files changed

+1442
-11
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
.idea/
33
.gradle/
44
build/
5+
artifacts/
56
out/
67
local.properties
78
**.iml
+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
apiVersion: v1alpha
2+
kind: espresso
3+
sauce:
4+
region: us-west-1
5+
# Controls how many suites are executed at the same time (sauce test env only).
6+
concurrency: 1
7+
metadata:
8+
name: Android benchmarks with Espresso
9+
tags:
10+
- benchmarks
11+
- android
12+
espresso:
13+
app: ./sentry-android-integration-tests/sentry-uitest-android-benchmark/build/outputs/apk/release/sentry-uitest-android-benchmark-release.apk
14+
testApp: ./sentry-android-integration-tests/sentry-uitest-android-benchmark/build/outputs/apk/androidTest/release/sentry-uitest-android-benchmark-release-androidTest.apk
15+
suites:
16+
name: "Android Benchmarks"
17+
devices:
18+
- name: "Google Pixel 2"
19+
platformVersion: 11
20+
- id: Google_Pixel_2_real_us
21+
testOptions:
22+
useTestOrchestrator: true
23+
# Controls what artifacts to fetch when the suite on Sauce Cloud has finished.
24+
artifacts:
25+
download:
26+
when: always
27+
match:
28+
- junit.xml
29+
directory: ./artifacts/
+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
apiVersion: v1alpha
2+
kind: espresso
3+
sauce:
4+
region: us-west-1
5+
# Controls how many suites are executed at the same time (sauce test env only).
6+
concurrency: 1
7+
metadata:
8+
name: Android end2end tests with Espresso
9+
tags:
10+
- e2e
11+
- android
12+
espresso:
13+
app: ./sentry-android-integration-tests/sentry-uitest-android/build/outputs/apk/release/sentry-uitest-android-release.apk
14+
testApp: ./sentry-android-integration-tests/sentry-uitest-android/build/outputs/apk/androidTest/release/sentry-uitest-android-release-androidTest.apk
15+
suites:
16+
name: "Android End2end"
17+
emulators:
18+
- name: "Android GoogleApi Emulator"
19+
orientation: portrait
20+
platformVersions:
21+
- "11.0"
22+
- "10.0"
23+
testOptions:
24+
useTestOrchestrator: true
25+
# Controls what artifacts to fetch when the suite on Sauce Cloud has finished.
26+
artifacts:
27+
download:
28+
when: always
29+
match:
30+
- junit.xml
31+
directory: ./artifacts/

build.gradle.kts

+4-2
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ apiValidation {
5656
"sentry-samples-spring-boot",
5757
"sentry-samples-spring-boot-webflux",
5858
"sentry-samples-netflix-dgs",
59+
"sentry-uitest-android",
60+
"sentry-uitest-android-benchmark",
5961
)
6062
)
6163
}
@@ -86,7 +88,7 @@ allprojects {
8688
}
8789

8890
subprojects {
89-
if (!this.name.contains("sample") && this.name != "sentry-test-support") {
91+
if (!this.name.contains("sample") && !this.name.contains("integration-tests") && this.name != "sentry-test-support") {
9092
apply<DistributionPlugin>()
9193

9294
val sep = File.separator
@@ -165,7 +167,7 @@ gradle.projectsEvaluated {
165167
"https://docs.spring.io/spring-boot/docs/current/api/"
166168
)
167169
subprojects
168-
.filter { !it.name.contains("sample") }
170+
.filter { !it.name.contains("sample") && !it.name.contains("integration-tests") }
169171
.forEach { proj ->
170172
proj.tasks.withType<Javadoc>().forEach { javadocTask ->
171173
source += javadocTask.source

buildSrc/src/main/java/Config.kt

+11-3
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,12 @@ object Config {
3939

4040
object Libs {
4141
val okHttpVersion = "4.9.2"
42-
val appCompat = "androidx.appcompat:appcompat:1.2.0"
42+
val appCompat = "androidx.appcompat:appcompat:1.3.0"
4343
val timber = "com.jakewharton.timber:timber:4.7.1"
4444
val okhttpBom = "com.squareup.okhttp3:okhttp-bom:$okHttpVersion"
4545
val okhttp = "com.squareup.okhttp3:okhttp"
4646
val leakCanary = "com.squareup.leakcanary:leakcanary-android:2.8.1"
47+
val constraintLayout = "androidx.constraintlayout:constraintlayout:2.1.3"
4748

4849
private val lifecycleVersion = "2.2.0"
4950
val lifecycleProcess = "androidx.lifecycle:lifecycle-process:$lifecycleVersion"
@@ -111,12 +112,19 @@ object Config {
111112
}
112113

113114
object TestLibs {
114-
private val androidxTestVersion = "1.4.0-rc01"
115+
private val androidxTestVersion = "1.4.0"
116+
private val espressoVersion = "3.4.0"
115117

118+
val androidJUnitRunner = "androidx.test.runner.AndroidJUnitRunner"
116119
val kotlinTestJunit = "org.jetbrains.kotlin:kotlin-test-junit:$kotlinVersion"
117120
val androidxCore = "androidx.test:core:$androidxTestVersion"
118121
val androidxRunner = "androidx.test:runner:$androidxTestVersion"
119-
val androidxJunit = "androidx.test.ext:junit:1.1.3-rc01"
122+
val androidxTestCoreKtx = "androidx.test:core-ktx:$androidxTestVersion"
123+
val androidxTestRules = "androidx.test:rules:$androidxTestVersion"
124+
val espressoCore = "androidx.test.espresso:espresso-core:$espressoVersion"
125+
val espressoIdlingResource = "androidx.test.espresso:espresso-idling-resource:$espressoVersion"
126+
val androidxTestOrchestrator = "androidx.test:orchestrator:1.4.1"
127+
val androidxJunit = "androidx.test.ext:junit:1.1.3"
120128
val androidxCoreKtx = "androidx.core:core-ktx:1.7.0"
121129
val robolectric = "org.robolectric:robolectric:4.7.3"
122130
val mockitoKotlin = "com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0"

sentry-android-core/build.gradle.kts

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ android {
1616
targetSdk = Config.Android.targetSdkVersion
1717
minSdk = Config.Android.minSdkVersion
1818

19-
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
19+
testInstrumentationRunner = Config.TestLibs.androidJUnitRunner
2020

2121
buildConfigField("String", "SENTRY_ANDROID_SDK_NAME", "\"${Config.Sentry.SENTRY_ANDROID_SDK_NAME}\"")
2222

Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/build
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Add project specific ProGuard rules here.
2+
# You can control the set of applied configuration files using the
3+
# proguardFiles setting in build.gradle.kts.
4+
#
5+
# For more details, see
6+
# http://developer.android.com/guide/developing/tools/proguard.html
7+
8+
# If your project uses WebView with JS, uncomment the following
9+
# and specify the fully qualified class name to the JavaScript interface
10+
# class:
11+
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12+
# public *;
13+
#}
14+
15+
# Uncomment this to preserve the line number information for
16+
# debugging stack traces.
17+
#-keepattributes SourceFile,LineNumberTable
18+
19+
# If you keep the line number information, uncomment this to
20+
# hide the original source file name.
21+
#-renamesourcefileattribute SourceFile
22+
23+
-dontobfuscate
24+
#Shrinking removes annotations and "unused classes" from test apk, so we don't shrink
25+
-dontshrink
26+
27+
-ignorewarnings
28+
29+
-keepattributes *Annotation*
30+
31+
-dontnote junit.framework.**
32+
-dontnote junit.runner.**
33+
34+
-dontwarn androidx.test.**
35+
-dontwarn org.junit.**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
import io.gitlab.arturbosch.detekt.Detekt
2+
import io.gitlab.arturbosch.detekt.extensions.DetektExtension
3+
import net.ltgt.gradle.errorprone.errorprone
4+
5+
plugins {
6+
id("com.android.application")
7+
kotlin("android")
8+
id(Config.QualityPlugins.errorProne)
9+
id(Config.QualityPlugins.gradleVersions)
10+
id(Config.QualityPlugins.detektPlugin)
11+
}
12+
13+
android {
14+
compileSdk = Config.Android.compileSdkVersion
15+
16+
defaultConfig {
17+
applicationId = "io.sentry.uitest.android.benchmark"
18+
minSdk = Config.Android.minSdkVersionNdk
19+
targetSdk = Config.Android.targetSdkVersion
20+
versionCode = 1
21+
versionName = "1.0.0"
22+
23+
testInstrumentationRunner = Config.TestLibs.androidJUnitRunner
24+
// Runs each test in its own instance of Instrumentation. This way they are isolated from
25+
// one another and get their own Application instance.
26+
// https://developer.android.com/training/testing/instrumented-tests/androidx-test-libraries/runner#enable-gradle
27+
// This doesn't work on some devices with Android 11+. Clearing package data resets permissions.
28+
// Check the readme for more info.
29+
// testInstrumentationRunnerArguments["clearPackageData"] = "true"
30+
}
31+
32+
buildFeatures {
33+
// Determines whether to support View Binding.
34+
// Note that the viewBinding.enabled property is now deprecated.
35+
viewBinding = true
36+
}
37+
38+
testOptions {
39+
execution = "ANDROIDX_TEST_ORCHESTRATOR"
40+
}
41+
42+
signingConfigs {
43+
getByName("debug") {
44+
storeFile = rootProject.file("debug.keystore")
45+
storePassword = "android"
46+
keyAlias = "androiddebugkey"
47+
keyPassword = "android"
48+
}
49+
}
50+
51+
testBuildType = System.getProperty("testBuildType", "debug")
52+
53+
buildTypes {
54+
getByName("debug") {
55+
isDebuggable = false
56+
isMinifyEnabled = true
57+
signingConfig = signingConfigs.getByName("debug")
58+
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "benchmark-proguard-rules.pro")
59+
}
60+
getByName("release") {
61+
isMinifyEnabled = true
62+
isShrinkResources = true
63+
signingConfig = signingConfigs.getByName("debug") // to be able to run release mode
64+
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "benchmark-proguard-rules.pro")
65+
}
66+
}
67+
68+
kotlinOptions {
69+
jvmTarget = JavaVersion.VERSION_1_8.toString()
70+
}
71+
72+
lint {
73+
warningsAsErrors = true
74+
checkDependencies = true
75+
76+
// We run a full lint analysis as build part in CI, so skip vital checks for assemble tasks.
77+
checkReleaseBuilds = false
78+
}
79+
80+
variantFilter {
81+
if (Config.Android.shouldSkipDebugVariant(buildType.name)) {
82+
ignore = true
83+
}
84+
}
85+
}
86+
87+
dependencies {
88+
89+
implementation(kotlin(Config.kotlinStdLib, org.jetbrains.kotlin.config.KotlinCompilerVersion.VERSION))
90+
91+
implementation(projects.sentryAndroidIntegrationTests.sentryUitestAndroid)
92+
implementation(projects.sentryAndroid)
93+
implementation(Config.Libs.appCompat)
94+
implementation(Config.Libs.androidxCore)
95+
implementation(Config.Libs.androidxRecylerView)
96+
implementation(Config.Libs.constraintLayout)
97+
implementation(Config.TestLibs.espressoIdlingResource)
98+
99+
compileOnly(Config.CompileOnly.nopen)
100+
errorprone(Config.CompileOnly.nopenChecker)
101+
errorprone(Config.CompileOnly.errorprone)
102+
errorprone(Config.CompileOnly.errorProneNullAway)
103+
104+
androidTestImplementation(Config.TestLibs.kotlinTestJunit)
105+
androidTestImplementation(Config.TestLibs.espressoCore)
106+
androidTestImplementation(Config.TestLibs.androidxTestCoreKtx)
107+
androidTestImplementation(Config.TestLibs.androidxRunner)
108+
androidTestImplementation(Config.TestLibs.androidxTestRules)
109+
androidTestImplementation(Config.TestLibs.androidxJunit)
110+
androidTestUtil(Config.TestLibs.androidxTestOrchestrator)
111+
}
112+
113+
tasks.withType<JavaCompile>().configureEach {
114+
options.errorprone {
115+
check("NullAway", net.ltgt.gradle.errorprone.CheckSeverity.ERROR)
116+
option("NullAway:AnnotatedPackages", "io.sentry")
117+
option("NullAway:UnannotatedSubPackages", "io.sentry.uitest.android.benchmark.databinding")
118+
}
119+
}
120+
121+
tasks.withType<Detekt> {
122+
// Target version of the generated JVM bytecode. It is used for type resolution.
123+
jvmTarget = JavaVersion.VERSION_1_8.toString()
124+
}
125+
126+
configure<DetektExtension> {
127+
buildUponDefaultConfig = true
128+
allRules = true
129+
}
130+
131+
kotlin {
132+
explicitApi()
133+
}

0 commit comments

Comments
 (0)