Skip to content

Commit 34446d9

Browse files
Merge 4dc470d into 0cc9262
2 parents 0cc9262 + 4dc470d commit 34446d9

File tree

12 files changed

+311
-1
lines changed

12 files changed

+311
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
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+
19+
jobs:
20+
build:
21+
name: Build sentry-uitest-android-critical
22+
runs-on: ubuntu-latest
23+
steps:
24+
- name: Checkout code
25+
uses: actions/checkout@v4
26+
27+
- name: Set up Java 17
28+
uses: actions/setup-java@v4
29+
with:
30+
distribution: 'temurin'
31+
java-version: '17'
32+
33+
- name: Setup Gradle
34+
uses: gradle/actions/setup-gradle@bb0c460cbf5354b0cddd15bacdf0d6aaa3e5a32b # pin@v3
35+
with:
36+
gradle-home-cache-cleanup: true
37+
38+
- name: Build debug APK
39+
run: make assembleUiTestCriticalRelease
40+
41+
- name: Upload APK artifact
42+
uses: actions/upload-artifact@v4
43+
with:
44+
name: ${{env.APK_ARTIFACT_NAME}}
45+
path: "${{env.BASE_PATH}}/${{env.BUILD_PATH}}/${{env.APK_NAME}}"
46+
retention-days: 1
47+
48+
run-maestro-tests:
49+
name: Run Maestro Tests
50+
needs: build
51+
runs-on: ubuntu-latest
52+
steps:
53+
- name: Checkout code
54+
uses: actions/checkout@v4
55+
56+
- name: Setup KVM
57+
shell: bash
58+
run: |
59+
# check if virtualization is supported...
60+
sudo apt install -y --no-install-recommends cpu-checker coreutils && echo "CPUs=$(nproc --all)" && kvm-ok
61+
# allow access to KVM to run the emulator
62+
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' \
63+
| sudo tee /etc/udev/rules.d/99-kvm4all.rules
64+
sudo udevadm control --reload-rules
65+
sudo udevadm trigger --name-match=kvm
66+
67+
- name: Download APK artifact
68+
uses: actions/download-artifact@v4
69+
with:
70+
name: ${{env.APK_ARTIFACT_NAME}}
71+
72+
- name: Install Maestro
73+
run: |
74+
brew tap mobile-dev-inc/tap
75+
brew install maestro
76+
77+
- name: Run Maestro tests
78+
run: |
79+
maestro test \
80+
"${{env.BASE_PATH}}/maestro" \
81+
--debug-output "${{env.BASE_PATH}}/maestro-logs"
82+
83+
- name: Upload Maestro test results
84+
if: failure()
85+
uses: actions/upload-artifact@v4
86+
with:
87+
name: maestro-logs
88+
path: "${{env.BASE_PATH}}/maestro-logs"
89+
retention-days: 1

Makefile

+8
Original file line numberDiff line numberDiff line change
@@ -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

+2-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ apiValidation {
7070
"sentry-uitest-android-benchmark",
7171
"test-app-plain",
7272
"test-app-sentry",
73-
"sentry-samples-netflix-dgs"
73+
"sentry-samples-netflix-dgs",
74+
"sentry-uitest-android-critical"
7475
)
7576
)
7677
}

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,64 @@
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 = 21
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+
}
46+
47+
dependencies {
48+
implementation(kotlin(Config.kotlinStdLib, org.jetbrains.kotlin.config.KotlinCompilerVersion.VERSION))
49+
implementation(Config.Libs.androidxCore)
50+
implementation(Config.Libs.composeActivity)
51+
implementation(Config.Libs.composeFoundation)
52+
implementation(Config.Libs.composeMaterial)
53+
implementation(Config.Libs.constraintLayout)
54+
implementation(projects.sentryAndroidCore)
55+
}
56+
57+
tasks.withType<Detekt> {
58+
// Target version of the generated JVM bytecode. It is used for type resolution.
59+
jvmTarget = JavaVersion.VERSION_1_8.toString()
60+
}
61+
62+
kotlin {
63+
explicitApi()
64+
}
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>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package io.sentry.uitest.android.critical
2+
3+
import android.os.Bundle
4+
import androidx.activity.ComponentActivity
5+
import androidx.activity.compose.setContent
6+
import androidx.compose.foundation.layout.Column
7+
import androidx.compose.material3.Button
8+
import androidx.compose.material3.MaterialTheme
9+
import androidx.compose.material3.Surface
10+
import androidx.compose.material3.Text
11+
import io.sentry.Sentry
12+
import java.io.File
13+
14+
class MainActivity : ComponentActivity() {
15+
override fun onCreate(savedInstanceState: Bundle?) {
16+
super.onCreate(savedInstanceState)
17+
val outboxPath = Sentry.getCurrentHub().options.outboxPath
18+
?: throw RuntimeException("Outbox path is not set.")
19+
20+
setContent {
21+
MaterialTheme {
22+
Surface() {
23+
Column() {
24+
Text(text = "Welcome!")
25+
Button(onClick = {
26+
throw RuntimeException("Crash the test app.")
27+
}) {
28+
Text("Crash")
29+
}
30+
Button(onClick = {
31+
Sentry.close()
32+
}) {
33+
Text("Close SDK")
34+
}
35+
Button(onClick = {
36+
val file = File(outboxPath, "corrupted.envelope")
37+
val corruptedEnvelopeContent = """
38+
{"event_id":"1990b5bc31904b7395fd07feb72daf1c","sdk":{"name":"sentry.java.android","version":"7.21.0"}}
39+
{"type":"test","length":50}
40+
""".trimIndent()
41+
file.writeText(corruptedEnvelopeContent)
42+
println("Wrote corrupted envelope to: ${file.absolutePath}")
43+
}) {
44+
Text("Write Corrupted Envelope")
45+
}
46+
}
47+
}
48+
}
49+
}
50+
}
51+
}

settings.gradle.kts

+1
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ include(
6161
"sentry-samples:sentry-samples-spring-boot-webflux",
6262
"sentry-samples:sentry-samples-spring-boot-webflux-jakarta",
6363
"sentry-samples:sentry-samples-netflix-dgs",
64+
"sentry-android-integration-tests:sentry-uitest-android-critical",
6465
"sentry-android-integration-tests:sentry-uitest-android-benchmark",
6566
"sentry-android-integration-tests:sentry-uitest-android",
6667
"sentry-android-integration-tests:test-app-plain",

0 commit comments

Comments
 (0)