Skip to content

Commit 4988d5b

Browse files
test(ui): Add critical tests run by Maestro (#3802)
1 parent 0cc9262 commit 4988d5b

File tree

13 files changed

+363
-4
lines changed

13 files changed

+363
-4
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
name: UI Tests Critical
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
9+
concurrency:
10+
group: ${{ github.workflow }}-${{ github.ref }}
11+
cancel-in-progress: true
12+
13+
env:
14+
BASE_PATH: "sentry-android-integration-tests/sentry-uitest-android-critical"
15+
BUILD_PATH: "build/outputs/apk/release"
16+
APK_NAME: "sentry-uitest-android-critical-release.apk"
17+
APK_ARTIFACT_NAME: "sentry-uitest-android-critical-release"
18+
MAESTRO_VERSION: "1.39.0"
19+
20+
jobs:
21+
build:
22+
name: Build sentry-uitest-android-critical
23+
runs-on: ubuntu-latest
24+
steps:
25+
- name: Checkout code
26+
uses: actions/checkout@v4
27+
28+
- name: Set up Java 17
29+
uses: actions/setup-java@v4
30+
with:
31+
distribution: 'temurin'
32+
java-version: '17'
33+
34+
- name: Setup Gradle
35+
uses: gradle/actions/setup-gradle@bb0c460cbf5354b0cddd15bacdf0d6aaa3e5a32b # pin@v3
36+
with:
37+
gradle-home-cache-cleanup: true
38+
39+
- name: Build debug APK
40+
run: make assembleUiTestCriticalRelease
41+
42+
- name: Upload APK artifact
43+
uses: actions/upload-artifact@v4
44+
with:
45+
name: ${{env.APK_ARTIFACT_NAME}}
46+
path: "${{env.BASE_PATH}}/${{env.BUILD_PATH}}/${{env.APK_NAME}}"
47+
retention-days: 1
48+
49+
run-maestro-tests:
50+
name: Run Maestro Tests
51+
needs: build
52+
runs-on: ubuntu-latest
53+
steps:
54+
- name: Checkout code
55+
uses: actions/checkout@v4
56+
57+
- name: Setup KVM
58+
shell: bash
59+
run: |
60+
# check if virtualization is supported...
61+
sudo apt install -y --no-install-recommends cpu-checker coreutils && echo "CPUs=$(nproc --all)" && kvm-ok
62+
# allow access to KVM to run the emulator
63+
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' \
64+
| sudo tee /etc/udev/rules.d/99-kvm4all.rules
65+
sudo udevadm control --reload-rules
66+
sudo udevadm trigger --name-match=kvm
67+
68+
- name: Download APK artifact
69+
uses: actions/download-artifact@v4
70+
with:
71+
name: ${{env.APK_ARTIFACT_NAME}}
72+
73+
- name: Install Maestro
74+
uses: dniHze/maestro-test-action@bda8a93211c86d0a05b7a4597c5ad134566fbde4 # [email protected]
75+
with:
76+
version: ${{env.MAESTRO_VERSION}}
77+
78+
- name: Run tests
79+
uses: reactivecircus/android-emulator-runner@f0d1ed2dcad93c7479e8b2f2226c83af54494915 # [email protected]
80+
with:
81+
api-level: 30
82+
force-avd-creation: false
83+
disable-animations: true
84+
disable-spellchecker: true
85+
target: 'aosp_atd'
86+
channel: canary # Necessary for ATDs
87+
emulator-options: >
88+
-no-window
89+
-no-snapshot-save
90+
-gpu swiftshader_indirect
91+
-noaudio
92+
-no-boot-anim
93+
-camera-back none
94+
-camera-front none
95+
-timezone US/Pacific
96+
script: |
97+
adb install -r -d "${{env.APK_NAME}}"
98+
maestro test "${{env.BASE_PATH}}/maestro" --debug-output "${{env.BASE_PATH}}/maestro-logs"
99+
100+
- name: Upload Maestro test results
101+
if: failure()
102+
uses: actions/upload-artifact@v4
103+
with:
104+
name: maestro-logs
105+
path: "${{env.BASE_PATH}}/maestro-logs"
106+
retention-days: 1

.github/workflows/system-tests-backend.yml

+30-3
Original file line numberDiff line numberDiff line change
@@ -46,19 +46,46 @@ jobs:
4646

4747
- name: Exclude android modules from build
4848
run: |
49-
sed -i -e '/.*"sentry-android-ndk",/d' -e '/.*"sentry-android",/d' -e '/.*"sentry-compose",/d' -e '/.*"sentry-android-core",/d' -e '/.*"sentry-android-fragment",/d' -e '/.*"sentry-android-navigation",/d' -e '/.*"sentry-android-okhttp",/d' -e '/.*"sentry-android-sqlite",/d' -e '/.*"sentry-android-timber",/d' -e '/.*"sentry-android-integration-tests:sentry-uitest-android-benchmark",/d' -e '/.*"sentry-android-integration-tests:sentry-uitest-android",/d' -e '/.*"sentry-android-integration-tests:test-app-sentry",/d' -e '/.*"sentry-samples:sentry-samples-android",/d' -e '/.*"sentry-android-replay",/d' settings.gradle.kts
49+
sed -i \
50+
-e '/.*"sentry-android-ndk",/d' \
51+
-e '/.*"sentry-android",/d' \
52+
-e '/.*"sentry-compose",/d' \
53+
-e '/.*"sentry-android-core",/d' \
54+
-e '/.*"sentry-android-fragment",/d' \
55+
-e '/.*"sentry-android-navigation",/d' \
56+
-e '/.*"sentry-android-okhttp",/d' \
57+
-e '/.*"sentry-android-sqlite",/d' \
58+
-e '/.*"sentry-android-timber",/d' \
59+
-e '/.*"sentry-android-integration-tests:sentry-uitest-android-benchmark",/d' \
60+
-e '/.*"sentry-android-integration-tests:sentry-uitest-android",/d' \
61+
-e '/.*"sentry-android-integration-tests:sentry-uitest-android-critical",/d' \
62+
-e '/.*"sentry-android-integration-tests:test-app-sentry",/d' \
63+
-e '/.*"sentry-samples:sentry-samples-android",/d' \
64+
-e '/.*"sentry-android-replay",/d' \
65+
settings.gradle.kts
5066
5167
- name: Exclude android modules from ignore list
5268
run: |
53-
sed -i -e '/.*"sentry-uitest-android",/d' -e '/.*"sentry-uitest-android-benchmark",/d' -e '/.*"test-app-sentry",/d' -e '/.*"sentry-samples-android",/d' build.gradle.kts
69+
sed -i \
70+
-e '/.*"sentry-uitest-android",/d' \
71+
-e '/.*"sentry-uitest-android-benchmark",/d' \
72+
-e '/.*"sentry-uitest-android-critical",/d' \
73+
-e '/.*"test-app-sentry",/d' \
74+
-e '/.*"sentry-samples-android",/d' \
75+
build.gradle.kts
5476
5577
- name: Build server jar
5678
run: |
5779
./gradlew :sentry-samples:${{ matrix.sample }}:bootJar
5880
5981
- name: Start server and run integration test for sentry-cli commands
6082
run: |
61-
test/system-test-sentry-server-start.sh > sentry-mock-server.txt 2>&1 & test/system-test-spring-server-start.sh "${{ matrix.sample }}" > spring-server.txt 2>&1 & test/wait-for-spring.sh && ./gradlew :sentry-samples:${{ matrix.sample }}:systemTest
83+
test/system-test-sentry-server-start.sh \
84+
> sentry-mock-server.txt 2>&1 & \
85+
test/system-test-spring-server-start.sh "${{ matrix.sample }}" \
86+
> spring-server.txt 2>&1 & \
87+
test/wait-for-spring.sh && \
88+
./gradlew :sentry-samples:${{ matrix.sample }}:systemTest
6289
6390
- name: Upload test results
6491
if: always()

Makefile

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.PHONY: all clean compile javadocs dryRelease update stop checkFormat format api assembleBenchmarkTestRelease assembleUiTestRelease createCoverageReports check preMerge publish
1+
.PHONY: all clean compile javadocs dryRelease update stop checkFormat format api assembleBenchmarkTestRelease assembleUiTestRelease assembleUiTestCriticalRelease createCoverageReports runUiTestCritical check preMerge publish
22

33
all: stop clean javadocs compile createCoverageReports
44
assembleBenchmarks: assembleBenchmarkTestRelease
@@ -53,6 +53,14 @@ assembleUiTestRelease:
5353
./gradlew :sentry-android-integration-tests:sentry-uitest-android:assembleRelease
5454
./gradlew :sentry-android-integration-tests:sentry-uitest-android:assembleAndroidTest -DtestBuildType=release
5555

56+
# Assemble release of the uitest-android-critical module
57+
assembleUiTestCriticalRelease:
58+
./gradlew :sentry-android-integration-tests:sentry-uitest-android-critical:assembleRelease
59+
60+
# Run Maestro tests for the uitest-android-critical module
61+
runUiTestCritical:
62+
./scripts/test-ui-critical.sh
63+
5664
# Create coverage reports
5765
# - Jacoco for Java & Android modules
5866
# - Kover for KMP modules e.g sentry-compose

build.gradle.kts

+1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ apiValidation {
6868
"sentry-samples-spring-boot-webflux-jakarta",
6969
"sentry-uitest-android",
7070
"sentry-uitest-android-benchmark",
71+
"sentry-uitest-android-critical",
7172
"test-app-plain",
7273
"test-app-sentry",
7374
"sentry-samples-netflix-dgs"

scripts/test-ui-critical.sh

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/usr/bin/env bash
2+
set -e
3+
4+
echo "Checking if ADB is installed..."
5+
if ! command -v adb &> /dev/null; then
6+
echo "ADB is not installed or not in PATH. Please install Android SDK platform tools and ensure ADB is in your PATH."
7+
exit 1
8+
fi
9+
10+
echo "Checking if an Android emulator is running..."
11+
if ! adb devices | grep -q "emulator"; then
12+
echo "No Android emulator is currently running. Please start an emulator before running this script."
13+
exit 1
14+
fi
15+
16+
echo "Checking if Maestro is installed..."
17+
if ! command -v maestro &> /dev/null; then
18+
echo "Maestro is not installed. Please install Maestro before running this script."
19+
exit 1
20+
fi
21+
22+
echo "Building the UI Test Critical app..."
23+
make assembleUiTestCriticalRelease
24+
25+
echo "Installing the UI Test Critical app on the emulator..."
26+
baseDir="sentry-android-integration-tests/sentry-uitest-android-critical"
27+
buildDir="build/outputs/apk/release"
28+
apkName="sentry-uitest-android-critical-release.apk"
29+
appPath="${baseDir}/${buildDir}/${apkName}"
30+
adb install -r -d "$appPath"
31+
32+
echo "Running the Maestro tests..."
33+
maestro test \
34+
"${baseDir}/maestro" \
35+
--debug-output "${baseDir}/maestro-logs"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/build
2+
/maestro-logs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import io.gitlab.arturbosch.detekt.Detekt
2+
3+
plugins {
4+
id("com.android.application")
5+
kotlin("android")
6+
}
7+
8+
android {
9+
compileSdk = Config.Android.compileSdkVersion
10+
namespace = "io.sentry.uitest.android.critical"
11+
12+
signingConfigs {
13+
getByName("debug") {
14+
// Debug config remains unchanged
15+
}
16+
}
17+
18+
defaultConfig {
19+
applicationId = "io.sentry.uitest.android.critical"
20+
minSdk = Config.Android.minSdkVersionCompose
21+
targetSdk = Config.Android.targetSdkVersion
22+
versionCode = 1
23+
versionName = "1.0"
24+
}
25+
26+
buildTypes {
27+
release {
28+
isMinifyEnabled = false
29+
signingConfig = signingConfigs.getByName("debug")
30+
proguardFiles(
31+
getDefaultProguardFile("proguard-android-optimize.txt"),
32+
"proguard-rules.pro"
33+
)
34+
}
35+
}
36+
kotlinOptions {
37+
jvmTarget = JavaVersion.VERSION_1_8.toString()
38+
}
39+
buildFeatures {
40+
compose = true
41+
}
42+
composeOptions {
43+
kotlinCompilerExtensionVersion = Config.androidComposeCompilerVersion
44+
}
45+
variantFilter {
46+
if (Config.Android.shouldSkipDebugVariant(buildType.name)) {
47+
ignore = true
48+
}
49+
}
50+
}
51+
52+
dependencies {
53+
implementation(kotlin(Config.kotlinStdLib, org.jetbrains.kotlin.config.KotlinCompilerVersion.VERSION))
54+
implementation(Config.Libs.androidxCore)
55+
implementation(Config.Libs.composeActivity)
56+
implementation(Config.Libs.composeFoundation)
57+
implementation(Config.Libs.composeMaterial)
58+
implementation(Config.Libs.constraintLayout)
59+
implementation(projects.sentryAndroidCore)
60+
}
61+
62+
tasks.withType<Detekt> {
63+
// Target version of the generated JVM bytecode. It is used for type resolution.
64+
jvmTarget = JavaVersion.VERSION_1_8.toString()
65+
}
66+
67+
kotlin {
68+
explicitApi()
69+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
appId: io.sentry.uitest.android.critical
2+
---
3+
- launchApp
4+
- tapOn: "Write Corrupted Envelope"
5+
# The close here ensures the next corrupted envelope
6+
# will be present on the next app launch
7+
- tapOn: "Close SDK"
8+
- tapOn: "Write Corrupted Envelope"
9+
- stopApp
10+
- launchApp
11+
- assertVisible: "Welcome!"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
appId: io.sentry.uitest.android.critical
2+
---
3+
- launchApp
4+
- tapOn: "Crash"
5+
- launchApp
6+
- assertVisible: "Welcome!"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
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.
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
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:tools="http://schemas.android.com/tools">
4+
5+
<application
6+
android:label="Sentry UI Tests Critical"
7+
android:supportsRtl="true"
8+
tools:targetApi="31">
9+
<meta-data android:name="io.sentry.dsn" android:value="https://[email protected]/5428559" />
10+
<meta-data android:name="io.sentry.debug" android:value="true" />
11+
<activity
12+
android:name=".MainActivity"
13+
android:exported="true">
14+
<intent-filter>
15+
<action android:name="android.intent.action.MAIN" />
16+
<category android:name="android.intent.category.LAUNCHER" />
17+
</intent-filter>
18+
</activity>
19+
</application>
20+
21+
</manifest>

0 commit comments

Comments
 (0)