Skip to content
Draft
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
2 changes: 1 addition & 1 deletion .github/workflows/agp-matrix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ jobs:
disable-spellchecker: true
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disk-size: 4096M
script: ./gradlew sentry-android-integration-tests:sentry-uitest-android:connectedReleaseAndroidTest -Denvironment=github --daemon
script: ./gradlew -p sentry-android-integration-tests :sentry-uitest-android:connectedReleaseAndroidTest -Denvironment=github --daemon

- name: Upload test results
if: always()
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/format-code.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ jobs:
run: |
./gradlew spotlessApply
./gradlew -p sentry-samples/sentry-samples-android spotlessApply
./gradlew -p sentry-android-integration-tests spotlessApply

# actions/checkout fetches only a single commit in a detached HEAD state. Therefore
# we need to pass the current branch, otherwise we can't commit the changes.
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/integration-tests-size.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,6 @@ jobs:
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}

- name: Size Analysis
run: ./gradlew :sentry-android-integration-tests:test-app-size:bundleRelease
run: ./gradlew -p sentry-android-integration-tests :test-app-size:bundleRelease
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
4 changes: 2 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ resolves the per-module test task, including integration test suites, for you.

### Android-Specific Commands
```bash
# Assemble Android test APKs
./gradlew :sentry-android-integration-tests:sentry-uitest-android:assembleRelease :sentry-android-integration-tests:sentry-uitest-android:assembleAndroidTest
# Assemble Android test APKs, in a separate Gradle build that includes this one
./gradlew -p sentry-android-integration-tests :sentry-uitest-android:assembleRelease :sentry-uitest-android:assembleAndroidTest

# Run critical UI tests
./scripts/test-ui-critical.sh
Expand Down
13 changes: 9 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
.PHONY: all clean compile javadocs dryRelease update checkFormat api assembleUiTestRelease assembleUiTestCriticalRelease runUiTestCritical check checkSampleAndroid preMerge publish
.PHONY: all clean compile javadocs dryRelease update checkFormat api assembleUiTestRelease assembleUiTestCriticalRelease runUiTestCritical check checkSampleAndroid checkIntegrationTests preMerge publish

all: stop clean javadocs compile
assembleUiTests: assembleUiTestRelease
preMerge: check checkSampleAndroid
preMerge: check checkSampleAndroid checkIntegrationTests
publish: clean dryRelease

# deep clean
Expand Down Expand Up @@ -30,18 +30,19 @@ update:
checkFormat:
./gradlew spotlessJavaCheck spotlessKotlinCheck
./gradlew -p sentry-samples/sentry-samples-android spotlessJavaCheck spotlessKotlinCheck
./gradlew -p sentry-android-integration-tests spotlessJavaCheck spotlessKotlinCheck

# Binary compatibility validator
api:
./gradlew apiDump

# Assemble release and Android test apk of the uitest-android module
assembleUiTestRelease:
./gradlew :sentry-android-integration-tests:sentry-uitest-android:assembleRelease :sentry-android-integration-tests:sentry-uitest-android:assembleAndroidTest
./gradlew -p sentry-android-integration-tests :sentry-uitest-android:assembleRelease :sentry-uitest-android:assembleAndroidTest

# Assemble release of the uitest-android-critical module
assembleUiTestCriticalRelease:
./gradlew :sentry-android-integration-tests:sentry-uitest-android-critical:assembleRelease
./gradlew -p sentry-android-integration-tests :sentry-uitest-android-critical:assembleRelease

# Run Maestro tests for the uitest-android-critical module
runUiTestCritical:
Expand All @@ -54,3 +55,7 @@ check:
# The Android sample is a separate build, so the root `check` doesn't reach it
checkSampleAndroid:
./gradlew -p sentry-samples/sentry-samples-android check

# The Android integration tests are a separate build, so the root `check` doesn't reach them
checkIntegrationTests:
./gradlew -p sentry-android-integration-tests check
3 changes: 0 additions & 3 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,6 @@ apiValidation {
"sentry-samples-spring-boot-4-otlp",
"sentry-samples-spring-boot-4-webflux",
"sentry-samples-ktor-client",
"sentry-uitest-android",
"sentry-uitest-android-critical",
"test-app-size",
"sentry-samples-netflix-dgs",
"sentry-samples-console-otlp",
"sentry-test-support"
Expand Down
4 changes: 4 additions & 0 deletions sentry-android-integration-tests/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
# Android performance-impact and integration tests

This directory is a separate Gradle build that includes the SDK build, so run its tasks with
`./gradlew -p sentry-android-integration-tests <task>`. The SDK build doesn't include it, so
`./gradlew` from the repository root doesn't build, lint or format these apps.

* [Espresso-based UI tests](./sentry-uitest-android) - run within SauceLabs (see /.sauce/*.yml)
* Also used for compatibility test matrix against new AGP versions
10 changes: 10 additions & 0 deletions sentry-android-integration-tests/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Loads the plugins once for every subproject, so they all share one classpath.
plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.kotlin.android) apply false
alias(libs.plugins.kotlin.compose) apply false
alias(libs.plugins.errorprone) apply false
alias(libs.plugins.detekt) apply false
alias(libs.plugins.gradle.versions) apply false
alias(libs.plugins.sentry) apply false
}
24 changes: 24 additions & 0 deletions sentry-android-integration-tests/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Gradle properties are per build, so this repeats what these apps need from the SDK build's
# gradle.properties. settings.gradle.kts reads the SDK version from that file.

org.gradle.jvmargs=-Xmx6g -XX:MaxMetaspaceSize=2g -XX:+CrashOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC
org.gradle.caching=true
org.gradle.parallel=true
org.gradle.configureondemand=true
org.gradle.configuration-cache=true
org.gradle.configuration-cache.parallel=true

android.useAndroidX=true
# AGP 9+ migration opt-outs until we remove kotlin-android plugin and adopt built-in Kotlin.
android.builtInKotlin=false
android.newDsl=false

android.defaults.buildfeatures.renderscript=false
android.defaults.buildfeatures.shaders=false
android.defaults.buildfeatures.aidl=false
android.defaults.buildfeatures.resvalues=false
android.nonTransitiveRClass=true

kotlin.stdlib.default.dependency=false

systemProp.org.gradle.internal.http.socketTimeout=120000
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@ plugins {
id("com.android.application")
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.compose)
id("io.sentry.spotless")
id("io.sentry.jdk-target")
}

val sentryVersion = libs.versions.sentry.get()

android {
compileSdk = libs.versions.compileSdk.get().toInt()
compileSdkMinor = libs.versions.compileSdkMinor.get().toInt()
Expand Down Expand Up @@ -47,7 +51,7 @@ dependencies {
implementation(libs.androidx.compose.material3)
implementation(libs.androidx.constraintlayout)
implementation(libs.androidx.core)
implementation(projects.sentryAndroidCore)
implementation("io.sentry:sentry-android-core:$sentryVersion")
}

tasks.withType<Detekt>().configureEach {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ By default the envelopes sent to relay are caught by a mock server which allows

# How to use

Simply run `./gradlew connectedCheck` to run all ui tests of all modules (requires a connected device, either physical or an emulator).
Simply run `./gradlew -p sentry-android-integration-tests connectedCheck` to run all ui tests of all modules (requires a connected device, either physical or an emulator).

# SauceLabs
To run on saucelabs execute following commands (need also `SAUCE_USERNAME` and `SAUCE_ACCESS_KEY` environment variables):
For End 2 End:
```
./gradlew :sentry-android-integration-tests:sentry-uitest-android:assembleRelease :sentry-android-integration-tests:sentry-uitest-android:assembleAndroidTest
./gradlew -p sentry-android-integration-tests :sentry-uitest-android:assembleRelease :sentry-uitest-android:assembleAndroidTest
saucectl run -c .sauce/sentry-uitest-android-end2end.yml
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ plugins {
alias(libs.plugins.errorprone)
alias(libs.plugins.gradle.versions)
alias(libs.plugins.detekt)
id("io.sentry.spotless")
id("io.sentry.jdk-target")
}

val sentryVersion = libs.versions.sentry.get()

android {
compileSdk = libs.versions.compileSdk.get().toInt()
compileSdkMinor = libs.versions.compileSdkMinor.get().toInt()
Expand Down Expand Up @@ -46,7 +50,7 @@ android {

signingConfigs {
getByName("debug") {
storeFile = rootProject.file("debug.keystore")
storeFile = file("../../debug.keystore")
storePassword = "android"
keyAlias = "androiddebugkey"
keyPassword = "android"
Expand Down Expand Up @@ -90,10 +94,10 @@ dependencies {
implementation(kotlin("stdlib-jdk8", getKotlinPluginVersion()))

if (applySentryIntegrations) {
implementation(projects.sentryAndroid)
implementation(projects.sentryCompose)
implementation("io.sentry:sentry-android:$sentryVersion")
implementation("io.sentry:sentry-compose:$sentryVersion")
} else {
implementation(projects.sentryAndroidCore)
implementation("io.sentry:sentry-android-core:$sentryVersion")
}
implementation(libs.androidx.appcompat)
implementation(libs.androidx.activity.compose)
Expand All @@ -112,7 +116,7 @@ dependencies {
errorprone(libs.nullaway)

androidTestUtil(libs.androidx.test.orchestrator)
androidTestImplementation(projects.sentryTestSupport)
androidTestImplementation("io.sentry:sentry-test-support:$sentryVersion")
androidTestImplementation(libs.androidx.test.core.ktx)
androidTestImplementation(libs.androidx.test.espresso.core)
androidTestImplementation(libs.androidx.test.ext.junit)
Expand All @@ -132,6 +136,12 @@ tasks.withType<JavaCompile>().configureEach {
}
}

detekt {
buildUponDefaultConfig = true
allRules = true
config.setFrom(file("../../detekt.yml"))
}

tasks.withType<Detekt>().configureEach {
// Target version of the generated JVM bytecode. It is used for type resolution.
jvmTarget = JavaVersion.VERSION_1_8.toString()
Expand Down
77 changes: 77 additions & 0 deletions sentry-android-integration-tests/settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// A standalone build that includes the SDK build, so it depends on the SDK through the same
// io.sentry:* coordinates an app would, and Gradle substitutes the SDK's projects for them.
// The SDK build doesn't include this one back, so its plugins and versions stay out of the SDK
// build. Run it with `./gradlew -p sentry-android-integration-tests <task>`.

pluginManagement {
repositories {
// Prefer local SAGP artifact if one exists; otherwise fall back to libs.versions.toml.
if (providers.gradleProperty("useSagp").isPresent) {
mavenLocal {
content {
includeGroup("io.sentry")
includeGroup("io.sentry.android.gradle")
}
}
}
mavenCentral()
gradlePluginPortal()
google()
}

// Every build in a composite must use the same AGP, so each build's settings applies the AGP
// matrix job's override.
System.getenv("VERSION_AGP")?.let { agpVersion ->
resolutionStrategy {
eachPlugin {
if (requested.id.id.startsWith("com.android")) {
useVersion(agpVersion)
}
}
}
}
}

plugins {
id("com.gradle.develocity") version "4.5.0"
id("com.gradle.common-custom-user-data-gradle-plugin") version "2.8.0"
}

develocity {
buildScan {
termsOfUseUrl.set("https://gradle.com/help/legal-terms-of-use")
termsOfUseAgree.set("yes")
}
}

// Gradle reads gradle.properties only for the build it belongs to, so read the SDK version from the
// SDK build's file.
val sentryVersion: String =
providers
.fileContents(layout.settingsDirectory.file("../gradle.properties"))
.asText
.map { java.util.Properties().apply { load(it.reader()) }.getProperty("versionName") }
.get()

dependencyResolutionManagement {
repositories {
google()
mavenCentral()
mavenLocal()
}
versionCatalogs {
create("libs") {
from(files("../gradle/libs.versions.toml"))
version("sentry", sentryVersion)
}
}
}

rootProject.name = "sentry-android-integration-tests"

includeBuild("..")

// For the io.sentry.spotless and io.sentry.jdk-target convention plugins.
includeBuild("../build-logic")

include("sentry-uitest-android", "sentry-uitest-android-critical", "test-app-size")
18 changes: 11 additions & 7 deletions sentry-android-integration-tests/test-app-size/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
plugins {
id("com.android.application")
id("io.sentry.android.gradle")
id("io.sentry.spotless")
id("io.sentry.jdk-target")
}

val sentryVersion = libs.versions.sentry.get()

android {
namespace = "io.sentry.tests.size"
compileSdk = libs.versions.compileSdk.get().toInt()
Expand All @@ -13,7 +17,7 @@ android {
minSdk = libs.versions.minSdk.get().toInt()
targetSdk = libs.versions.targetSdk.get().toInt()
versionCode = 1
versionName = project.version.toString()
versionName = sentryVersion
}

buildTypes {
Expand Down Expand Up @@ -42,12 +46,12 @@ configurations.configureEach {
}

dependencies {
implementation(projects.sentryAndroid)
implementation(projects.sentryAndroidTimber)
implementation(projects.sentryAndroidSqlite)
implementation(projects.sentryOkhttp)
implementation(projects.sentryCompose)
implementation(projects.sentryAndroidFragment)
implementation("io.sentry:sentry-android:$sentryVersion")
implementation("io.sentry:sentry-android-timber:$sentryVersion")
implementation("io.sentry:sentry-android-sqlite:$sentryVersion")
implementation("io.sentry:sentry-okhttp:$sentryVersion")
implementation("io.sentry:sentry-compose:$sentryVersion")
implementation("io.sentry:sentry-android-fragment:$sentryVersion")
}

sentry {
Expand Down
3 changes: 0 additions & 3 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,5 @@ include(
"sentry-samples:sentry-samples-spring-boot-4-otlp",
"sentry-samples:sentry-samples-spring-boot-4-webflux",
"sentry-samples:sentry-samples-netflix-dgs",
"sentry-android-integration-tests:sentry-uitest-android-critical",
"sentry-android-integration-tests:sentry-uitest-android",
"sentry-android-integration-tests:test-app-size",
"sentry-samples:sentry-samples-openfeign"
)
Loading