-
-
Notifications
You must be signed in to change notification settings - Fork 53
chore: Add integration tests for Android #1146
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
tustanivsky
wants to merge
46
commits into
main
Choose a base branch
from
chore/android-tests
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 45 commits
Commits
Show all changes
46 commits
Select commit
Hold shift + click to select a range
7042674
Update sample app to receive input args on Android (required for test…
tustanivsky 6e34b25
Add Android integration tests to CI
tustanivsky 588aada
Comment crash capturing test
tustanivsky c82a55e
Fix test script
tustanivsky 6b14d0a
Fix minor issues
tustanivsky a7bb5e3
Rename vars
tustanivsky 7b3ab68
Clean up
tustanivsky a47a7ea
Better comments
tustanivsky 35c488b
Refactor
tustanivsky 297cf36
Fix workflow
tustanivsky d62218d
Fix
tustanivsky 35862ce
Simplify mechanism to pass input args to Android app
tustanivsky 3bc3f33
Clean up comments
tustanivsky 281af4a
Merge branch 'main' into chore/android-tests
tustanivsky c9079bc
Test SauceLabs
tustanivsky 957c826
Add separate SauceLabs test script
tustanivsky 11d997a
Fix log retrieval
tustanivsky f87da41
Fix
tustanivsky 4ea1b22
Rename script for running Android integration tests locally
tustanivsky d09d95e
Update readme
tustanivsky 89c6014
Revert CI tweaks for faster iterations
tustanivsky b99f9a6
Clean up
tustanivsky 4c7547b
Fix
tustanivsky f0bb43d
Fix typo
tustanivsky 5fea785
Limit android e2e tests to 2 parallel jobs
tustanivsky 9eeb769
Remove Pester install step as it is redundant
tustanivsky aeb2f78
Rename test scripts
tustanivsky c6777cc
Clean up
tustanivsky d03ecbb
Rework SauceLabs API requests
tustanivsky 30d3be2
Simplify logs retrieval
tustanivsky 532fa78
Remove unnecessary quotes
tustanivsky 3e09c20
Configure new SauceLabs credentials
tustanivsky 1c27be6
Change test device
tustanivsky 3d8a9c7
Change SauceLabs test job name title
tustanivsky 7dbcb78
Fix android test results upload check
tustanivsky e4a7195
Make SauceLabs device name configurable
tustanivsky e43d13f
Fix sample app
tustanivsky c218ae8
Try using app-runner Android providers for running tests
tustanivsky 25fe615
Fix param name
tustanivsky 69f3e65
Pass device name to SauceLabs provider
tustanivsky 0b5fa5f
Connect to SauceLabs device set in env var
tustanivsky 3b20dc8
Bump app-runner
tustanivsky c22b2c6
Merge android test scripts
tustanivsky 49d01ee
Remove platform-specific test scripts
tustanivsky e4d0fb4
Add SauceLabs session name override
tustanivsky 95d2fe6
Bump app-runner
tustanivsky File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| on: | ||
| workflow_call: | ||
| inputs: | ||
| unreal-version: | ||
| required: true | ||
| type: string | ||
|
|
||
| jobs: | ||
| integration-test: | ||
| name: Integration Test | ||
| runs-on: ubuntu-latest | ||
|
|
||
| env: | ||
| SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }} | ||
| SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }} | ||
| GITHUB_TOKEN: ${{ github.token }} | ||
| SAUCE_REGION: us-west-1 | ||
| SAUCE_DEVICE_NAME: Samsung_Galaxy_S23_15_real_sjc1 | ||
| SAUCE_SESSION_NAME: UE ${{ inputs.unreal-version }} Android Integration Test | ||
|
|
||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| submodules: recursive | ||
|
|
||
| - name: Download sample build | ||
| uses: actions/download-artifact@v4 | ||
| with: | ||
| name: UE ${{ inputs.unreal-version }} sample build (Android) | ||
| path: sample-build | ||
|
|
||
| - name: Run integration tests | ||
| id: run-integration-tests | ||
| shell: pwsh | ||
| working-directory: integration-test | ||
| env: | ||
| SENTRY_UNREAL_TEST_DSN: ${{ secrets.SENTRY_UNREAL_TEST_DSN }} | ||
| SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_API_TOKEN }} | ||
| SENTRY_UNREAL_TEST_APP_PATH: ${{ github.workspace }}/sample-build/SentryPlayground-arm64.apk | ||
| run: | | ||
| cmake -B build -S . | ||
| $Container = New-PesterContainer -Path 'Integration.Android.Tests.ps1' -Data @{ Platform = 'SauceLabs' } | ||
| Invoke-Pester -Container $Container -CI | ||
|
|
||
| - name: Upload integration test output | ||
| if: ${{ always() && steps.run-integration-tests.outcome == 'failure' }} | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: UE ${{ inputs.unreal-version }} integration test output (Android) | ||
| path: | | ||
| integration-test/output/ | ||
| retention-days: 14 | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,280 @@ | ||
| # Integration tests for Sentry Unreal SDK on Android | ||
| # Supports both ADB (local devices/emulators) and SauceLabs (cloud devices) | ||
| # | ||
| # Usage: | ||
| # # Default (uses ADB) | ||
| # Invoke-Pester Integration.Android.Tests.ps1 | ||
| # | ||
| # # Explicit platform selection with Pester containers | ||
| # $Container = New-PesterContainer -Path 'Integration.Android.Tests.ps1' -Data @{ Platform = 'Adb' } | ||
| # Invoke-Pester -Container $Container | ||
| # | ||
| # $Container = New-PesterContainer -Path 'Integration.Android.Tests.ps1' -Data @{ Platform = 'SauceLabs' } | ||
| # Invoke-Pester -Container $Container | ||
| # | ||
| # Requires: | ||
| # - Pre-built APK | ||
| # - Environment variables: SENTRY_UNREAL_TEST_DSN, SENTRY_AUTH_TOKEN, SENTRY_UNREAL_TEST_APP_PATH | ||
| # | ||
| # For ADB: | ||
| # - Android emulator or device connected via ADB | ||
| # | ||
| # For SauceLabs: | ||
| # - SAUCE_USERNAME, SAUCE_ACCESS_KEY, SAUCE_REGION, SAUCE_DEVICE_NAME | ||
|
|
||
| param( | ||
| [Parameter(Mandatory = $false)] | ||
| [ValidateSet('Adb', 'SauceLabs')] | ||
| [string]$Platform = 'Adb' | ||
| ) | ||
|
|
||
| Set-StrictMode -Version Latest | ||
| $ErrorActionPreference = 'Stop' | ||
|
|
||
| BeforeAll { | ||
| # Map friendly platform name to app-runner platform name | ||
| $appRunnerPlatform = if ($Platform -eq 'Adb') { 'AndroidAdb' } else { 'AndroidSauceLabs' } | ||
|
|
||
| Write-Host "Running Android tests with platform: $Platform (app-runner: $appRunnerPlatform)" -ForegroundColor Cyan | ||
|
|
||
| # Check if configuration file exists | ||
| $configFile = "$PSScriptRoot/TestConfig.local.ps1" | ||
| if (-not (Test-Path $configFile)) { | ||
| throw "Configuration file '$configFile' not found. Run 'cmake -B build -S .' first" | ||
| } | ||
|
|
||
| # Load configuration (provides $global:AppRunnerPath) | ||
| . $configFile | ||
|
|
||
| # Import app-runner modules (SentryApiClient, test utilities) | ||
| . "$global:AppRunnerPath/import-modules.ps1" | ||
|
|
||
| # Validate environment variables (test-specific only, not provider-specific) | ||
| $script:DSN = $env:SENTRY_UNREAL_TEST_DSN | ||
| $script:AuthToken = $env:SENTRY_AUTH_TOKEN | ||
| $script:ApkPath = $env:SENTRY_UNREAL_TEST_APP_PATH | ||
|
|
||
| if (-not $script:DSN) { | ||
| throw "Environment variable SENTRY_UNREAL_TEST_DSN must be set" | ||
| } | ||
|
|
||
| if (-not $script:AuthToken) { | ||
| throw "Environment variable SENTRY_AUTH_TOKEN must be set" | ||
| } | ||
|
|
||
| if (-not $script:ApkPath) { | ||
| throw "Environment variable SENTRY_UNREAL_TEST_APP_PATH must be set" | ||
| } | ||
|
|
||
| # Validate app path | ||
| if (-not (Test-Path $script:ApkPath)) { | ||
| throw "Application not found at: $script:ApkPath" | ||
| } | ||
|
|
||
| # Connect to Sentry API | ||
| Write-Host "Connecting to Sentry API..." -ForegroundColor Yellow | ||
| Connect-SentryApi -DSN $script:DSN -ApiToken $script:AuthToken | ||
|
|
||
| # Create output directory | ||
| $script:OutputDir = "$PSScriptRoot/output" | ||
| if (-not (Test-Path $script:OutputDir)) { | ||
| New-Item -ItemType Directory -Path $script:OutputDir | Out-Null | ||
| } | ||
|
|
||
| $script:PackageName = "io.sentry.unreal.sample" | ||
| $script:ActivityName = "$script:PackageName/com.epicgames.unreal.GameActivity" | ||
|
|
||
| # Connect to Android device (provider validates its own env vars) | ||
| Write-Host "Connecting to Android via $Platform..." -ForegroundColor Yellow | ||
| Connect-Device -Platform $appRunnerPlatform | ||
|
|
||
| # Install APK | ||
| Write-Host "Installing APK via $Platform..." -ForegroundColor Yellow | ||
| Install-DeviceApp -Path $script:ApkPath | ||
|
|
||
| # ========================================== | ||
| # RUN 1: Crash test - creates minidump | ||
| # ========================================== | ||
| # The crash is captured but NOT uploaded yet (Android behavior). | ||
| # TODO: Re-enable once Android SDK tag persistence is fixed (`test.crash_id` tag set before crash is not synced to the captured crash on Android) | ||
|
|
||
| # Write-Host "Running crash-capture test (will crash)..." -ForegroundColor Yellow | ||
| # $cmdlineCrashArgs = "-e cmdline -crash-capture" | ||
| # $global:AndroidCrashResult = Invoke-DeviceApp -ExecutablePath $script:ActivityName -Arguments $cmdlineCrashArgs | ||
|
|
||
| # Write-Host "Crash test exit code: $($global:AndroidCrashResult.ExitCode)" -ForegroundColor Cyan | ||
|
|
||
| # ========================================== | ||
| # RUN 2: Message test - uploads crash from Run 1 + captures message | ||
| # ========================================== | ||
| # Currently we need to run again so that Sentry sends the crash event captured during the previous app session. | ||
|
|
||
| Write-Host "Running message-capture test on $Platform..." -ForegroundColor Yellow | ||
| $cmdlineMessageArgs = "-e cmdline -message-capture" | ||
| $global:AndroidMessageResult = Invoke-DeviceApp -ExecutablePath $script:ActivityName -Arguments $cmdlineMessageArgs | ||
|
|
||
| Write-Host "Message test exit code: $($global:AndroidMessageResult.ExitCode)" -ForegroundColor Cyan | ||
| } | ||
|
|
||
| Describe "Sentry Unreal Android Integration Tests ($Platform)" { | ||
|
|
||
| # ========================================== | ||
| # NOTE: Crash Capture Tests are DISABLED due to tag sync issue | ||
| # Uncomment when Android SDK tag persistence is fixed | ||
| # ========================================== | ||
| # Context "Crash Capture Tests" { | ||
| # BeforeAll { | ||
| # # Crash event is sent during the MESSAGE run (Run 2) | ||
| # # But the crash_id comes from the CRASH run (Run 1) | ||
| # $CrashResult = $global:AndroidCrashResult | ||
| # $CrashEvent = $null | ||
| # | ||
| # # Parse crash event ID from crash run output | ||
| # $eventIds = Get-EventIds -AppOutput $CrashResult.Output -ExpectedCount 1 | ||
| # | ||
| # if ($eventIds -and $eventIds.Count -gt 0) { | ||
| # Write-Host "Crash ID captured: $($eventIds[0])" -ForegroundColor Cyan | ||
| # $crashId = $eventIds[0] | ||
| # | ||
| # # Fetch crash event using the tag (event was sent during message run) | ||
| # try { | ||
| # $CrashEvent = Get-SentryTestEvent -TagName 'test.crash_id' -TagValue "$crashId" | ||
| # Write-Host "Crash event fetched from Sentry successfully" -ForegroundColor Green | ||
| # } catch { | ||
| # Write-Host "Failed to fetch crash event from Sentry: $_" -ForegroundColor Red | ||
| # } | ||
| # } else { | ||
| # Write-Host "Warning: No crash event ID found in output" -ForegroundColor Yellow | ||
| # } | ||
| # } | ||
| # | ||
| # It "Should output event ID before crash" { | ||
| # $eventIds = Get-EventIds -AppOutput $CrashResult.Output -ExpectedCount 1 | ||
| # $eventIds | Should -Not -BeNullOrEmpty | ||
| # $eventIds.Count | Should -Be 1 | ||
| # } | ||
| # | ||
| # It "Should capture crash event in Sentry (uploaded during next run)" { | ||
| # $CrashEvent | Should -Not -BeNullOrEmpty | ||
| # } | ||
| # | ||
| # It "Should have correct event type and platform" { | ||
| # $CrashEvent.type | Should -Be 'error' | ||
| # $CrashEvent.platform | Should -Be 'native' | ||
| # } | ||
| # | ||
| # It "Should have exception information" { | ||
| # $CrashEvent.exception | Should -Not -BeNullOrEmpty | ||
| # $CrashEvent.exception.values | Should -Not -BeNullOrEmpty | ||
| # } | ||
| # | ||
| # It "Should have stack trace" { | ||
| # $exception = $CrashEvent.exception.values[0] | ||
| # $exception.stacktrace | Should -Not -BeNullOrEmpty | ||
| # $exception.stacktrace.frames | Should -Not -BeNullOrEmpty | ||
| # } | ||
| # | ||
| # It "Should have user context" { | ||
| # $CrashEvent.user | Should -Not -BeNullOrEmpty | ||
| # $CrashEvent.user.username | Should -Be 'TestUser' | ||
| # $CrashEvent.user.email | Should -Be '[email protected]' | ||
| # $CrashEvent.user.id | Should -Be '12345' | ||
| # } | ||
| # | ||
| # It "Should have test.crash_id tag for correlation" { | ||
| # $tags = $CrashEvent.tags | ||
| # $crashIdTag = $tags | Where-Object { $_.key -eq 'test.crash_id' } | ||
| # $crashIdTag | Should -Not -BeNullOrEmpty | ||
| # $crashIdTag.value | Should -Not -BeNullOrEmpty | ||
| # } | ||
| # | ||
| # It "Should have integration test tag" { | ||
| # $tags = $CrashEvent.tags | ||
| # ($tags | Where-Object { $_.key -eq 'test.suite' }).value | Should -Be 'integration' | ||
| # } | ||
| # | ||
| # It "Should have breadcrumbs from before crash" { | ||
| # $CrashEvent.breadcrumbs | Should -Not -BeNullOrEmpty | ||
| # $CrashEvent.breadcrumbs.values | Should -Not -BeNullOrEmpty | ||
| # } | ||
| # } | ||
|
|
||
| Context "Message Capture Tests" { | ||
| BeforeAll { | ||
| $MessageResult = $global:AndroidMessageResult | ||
| $MessageEvent = $null | ||
|
|
||
| # Parse event ID from output | ||
| $eventIds = Get-EventIds -AppOutput $MessageResult.Output -ExpectedCount 1 | ||
|
|
||
| if ($eventIds -and $eventIds.Count -gt 0) { | ||
| Write-Host "Message event ID captured: $($eventIds[0])" -ForegroundColor Cyan | ||
|
|
||
| # Fetch event from Sentry (with polling) | ||
| try { | ||
| $MessageEvent = Get-SentryTestEvent -EventId $eventIds[0] | ||
| Write-Host "Message event fetched from Sentry successfully" -ForegroundColor Green | ||
| } | ||
| catch { | ||
| Write-Host "Failed to fetch message event from Sentry: $_" -ForegroundColor Red | ||
| } | ||
| } | ||
| else { | ||
| Write-Host "Warning: No message event ID found in output" -ForegroundColor Yellow | ||
| } | ||
| } | ||
|
|
||
| It "Should output event ID" { | ||
| $eventIds = Get-EventIds -AppOutput $MessageResult.Output -ExpectedCount 1 | ||
| $eventIds | Should -Not -BeNullOrEmpty | ||
| $eventIds.Count | Should -Be 1 | ||
| } | ||
|
|
||
| It "Should output TEST_RESULT with success" { | ||
| $testResultLine = $MessageResult.Output | Where-Object { $_ -match 'TEST_RESULT:' } | ||
| $testResultLine | Should -Not -BeNullOrEmpty | ||
| $testResultLine | Should -Match '"success"\s*:\s*true' | ||
| } | ||
|
|
||
| It "Should capture message event in Sentry" { | ||
| $MessageEvent | Should -Not -BeNullOrEmpty | ||
| } | ||
|
|
||
| It "Should have correct platform" { | ||
| # Android events are captured from Java layer, so platform is 'java' not 'native' | ||
| $MessageEvent.platform | Should -Be 'java' | ||
| } | ||
|
|
||
| It "Should have message content" { | ||
| $MessageEvent.message | Should -Not -BeNullOrEmpty | ||
| $MessageEvent.message.formatted | Should -Match 'Integration test message' | ||
| } | ||
|
|
||
| It "Should have user context" { | ||
| $MessageEvent.user | Should -Not -BeNullOrEmpty | ||
| $MessageEvent.user.username | Should -Be 'TestUser' | ||
| } | ||
|
|
||
| It "Should have integration test tag" { | ||
| $tags = $MessageEvent.tags | ||
| ($tags | Where-Object { $_.key -eq 'test.suite' }).value | Should -Be 'integration' | ||
| } | ||
|
|
||
| It "Should have breadcrumbs" { | ||
| $MessageEvent.breadcrumbs | Should -Not -BeNullOrEmpty | ||
| $MessageEvent.breadcrumbs.values | Should -Not -BeNullOrEmpty | ||
| } | ||
| } | ||
| } | ||
|
|
||
| AfterAll { | ||
| # Disconnect from Android device | ||
| Write-Host "Disconnecting from $Platform..." -ForegroundColor Yellow | ||
| Disconnect-Device | ||
|
|
||
| # Disconnect from Sentry API | ||
| Write-Host "Disconnecting from Sentry API..." -ForegroundColor Yellow | ||
| Disconnect-SentryApi | ||
|
|
||
| Write-Host "Integration tests complete" -ForegroundColor Green | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.