Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
65bfb99
First iteration
bitsandfoxes Feb 13, 2026
d90e410
Fixes
bitsandfoxes Feb 13, 2026
323d187
Remove startup awake span assertion
bitsandfoxes Feb 16, 2026
5b30b7d
Fixed desktop test validation order
bitsandfoxes Feb 16, 2026
20554a9
Fixed single-line pwsh command
bitsandfoxes Feb 16, 2026
b899cc5
strictmode workaround
bitsandfoxes Feb 16, 2026
7c93e12
Baking the DSN
bitsandfoxes Feb 16, 2026
3dceec0
.
bitsandfoxes Feb 16, 2026
e999f6e
Fix env
bitsandfoxes Feb 16, 2026
b6fc8a2
.
bitsandfoxes Feb 16, 2026
f39fb13
Fix double event capture
bitsandfoxes Feb 16, 2026
3902b68
Fixed log grouping
bitsandfoxes Feb 16, 2026
0638d92
Debug log level
bitsandfoxes Feb 16, 2026
f05f223
Fixing 'dist'
bitsandfoxes Feb 16, 2026
160f355
fallback to activity
bitsandfoxes Feb 16, 2026
f5e1c10
Do some fake work
bitsandfoxes Feb 16, 2026
10ba69c
Drop stripping level for older than 6
bitsandfoxes Feb 17, 2026
c2e1256
Fixed vulkan issues
bitsandfoxes Feb 17, 2026
a0318cf
Code generation settings and log output
bitsandfoxes Feb 17, 2026
aa815ff
AOT check
bitsandfoxes Feb 17, 2026
fc3c734
Bumped .NET to 'main'
bitsandfoxes Feb 19, 2026
ab6d14e
Mark crash-capture skipped tests as Skipped instead of silently passing
bitsandfoxes Feb 19, 2026
af19c5e
Extending the tests of scope sync to the crash tests
bitsandfoxes Feb 19, 2026
9588ff9
Skip app context assertion for crash-capture on Android
bitsandfoxes Feb 19, 2026
0ffce53
Improved on the crashed second run validation
bitsandfoxes Feb 19, 2026
8be86be
Incremental fix
bitsandfoxes Feb 19, 2026
d6c5084
Activity detection instead of try-catch
bitsandfoxes Feb 19, 2026
bf353f6
Get built-time check back in
bitsandfoxes Feb 20, 2026
d0e10ea
feedback
bitsandfoxes Feb 20, 2026
0cc6ab4
skip 'dist' for now
bitsandfoxes Feb 20, 2026
641f5e1
Apply suggestion from @bitsandfoxes
bitsandfoxes Feb 20, 2026
36943c3
Migrate iOS CI to use app-runner
bitsandfoxes Feb 23, 2026
8322cbd
bump app-runner
bitsandfoxes Feb 23, 2026
9cf1ec5
fixes
bitsandfoxes Feb 24, 2026
7f03d3f
Fix iOS integration test configuration
bitsandfoxes Feb 24, 2026
5915218
Timeout and retry
bitsandfoxes Feb 24, 2026
0965ded
machine feedback
bitsandfoxes Feb 25, 2026
0457ff8
Merge branch 'main' into feat/app-runner-ios
bitsandfoxes Feb 25, 2026
5f18483
timeout tweaks
bitsandfoxes Feb 25, 2026
5af6bdd
.
bitsandfoxes Feb 25, 2026
0f34226
Merge branch 'main' into feat/app-runner-ios
bitsandfoxes Feb 26, 2026
3d035ca
bumped app-runner
bitsandfoxes Feb 26, 2026
5a96ca9
Scope app context crash-capture skip to iOS only
bitsandfoxes Feb 26, 2026
8ce299c
Merge branch 'main' into feat/app-runner-ios
bitsandfoxes Feb 26, 2026
8803de8
bumped app-runner
bitsandfoxes Mar 3, 2026
8d11278
review
bitsandfoxes Mar 5, 2026
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
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -303,14 +303,15 @@ jobs:
init-type: ${{ matrix.init-type }}

smoke-test-run-ios:
name: Run iOS ${{ matrix.unity-version }} Smoke Test
name: Run iOS ${{ matrix.unity-version }} Integration Test
if: ${{ !startsWith(github.ref, 'refs/heads/release/') }}
needs: [smoke-test-compile-ios, create-unity-matrix]
uses: ./.github/workflows/smoke-test-run-ios.yml
with:
unity-version: ${{ matrix.unity-version }}
ios-version: ${{ matrix.ios-version }}
init-type: ${{ matrix.init-type }}
secrets: inherit
strategy:
fail-fast: false
matrix:
Expand Down
7 changes: 4 additions & 3 deletions .github/workflows/smoke-test-build-ios.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,10 @@ jobs:
run: ./test/Scripts.Integration.Test/add-sentry.ps1 -UnityPath "$env:UNITY_PATH" -PackagePath "test-package-release"

- name: Configure Sentry
run: ./test/Scripts.Integration.Test/configure-sentry.ps1 -UnityPath "$env:UNITY_PATH" -Platform "$env:BUILD_PLATFORM" -CheckSymbols
run: ./test/Scripts.Integration.Test/configure-sentry.ps1 -UnityPath "$env:UNITY_PATH" -Platform "$env:BUILD_PLATFORM" -CheckSymbols -TestMode "integration"
env:
BUILD_PLATFORM: ${{ matrix.build_platform }}
SENTRY_DSN: ${{ secrets.SENTRY_TEST_DSN }}

- name: Build Project with runtime initialization
run: ./test/Scripts.Integration.Test/build-project.ps1 -UnityPath "$env:UNITY_PATH" -Platform "$env:BUILD_PLATFORM" -CheckSymbols:$false -UnityVersion "$env:UNITY_VERSION"
Expand All @@ -122,9 +123,9 @@ jobs:
path: test-app-runtime.tar.gz
retention-days: 14

- name: Overwrite OptionsConfiguration for build-time initialization
- name: Overwrite IntegrationOptionsConfiguration for build-time initialization
run: |
$optionsPath = "samples/IntegrationTest/Assets/Scripts/OptionsConfiguration.cs"
$optionsPath = "samples/IntegrationTest/Assets/Scripts/IntegrationOptionsConfiguration.cs"
$content = Get-Content $optionsPath -Raw
$content = $content -replace 'IosNativeInitializationType = NativeInitializationType.Runtime', 'IosNativeInitializationType = NativeInitializationType.BuildTime'
Set-Content $optionsPath $content
Expand Down
37 changes: 26 additions & 11 deletions .github/workflows/smoke-test-run-ios.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: "SmokeTest: Run iOS"
name: "IntegrationTest: Run iOS"
on:
workflow_call:
inputs:
Expand All @@ -14,7 +14,7 @@ on:
# Map the workflow outputs to job outputs
outputs:
status:
description: "Smoke test status"
description: "Integration test status"
value: ${{ jobs.run.outputs.status }}

defaults:
Expand All @@ -27,16 +27,23 @@ jobs:
runs-on: macos-14 # Pinning to get the oldest, supported version of iOS simulator
# Map the job outputs to step outputs
outputs:
status: ${{ steps.smoke-test.outputs.status }}
status: ${{ steps.integration-test.outputs.status }}
env:
UNITY_VERSION: ${{ inputs.unity-version }}
IOS_VERSION: ${{ inputs.ios-version }}
INIT_TYPE: ${{ inputs.init-type }}
ARTIFACTS_PATH: samples/IntegrationTest/test-artifacts/
SENTRY_TEST_DSN: ${{ secrets.SENTRY_TEST_DSN }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}

steps:
- name: Checkout
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3

- name: Initialize app-runner submodule
run: git submodule update --init modules/app-runner
shell: bash

- name: Download app artifact
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
Expand All @@ -53,13 +60,21 @@ jobs:
with:
xcode-version: '15.0' # to run iOS 17.0 we need Xcode 15.0

- name: Run iOS Smoke Tests
id: smoke-test
- name: Run iOS Integration Tests
id: integration-test
timeout-minutes: 20
run: |
$runtime = "${env:IOS_VERSION}"
If ($runtime -ne "latest")
{
$runtime = "iOS " + $runtime
}
./Scripts/smoke-test-ios.ps1 Test "$runtime" -IsIntegrationTest
$env:SENTRY_TEST_APP = "samples/IntegrationTest/Build/IntegrationTest.app"
$env:SENTRY_IOS_VERSION = "${{ inputs.ios-version }}"
Invoke-Pester -Path test/IntegrationTest/Integration.Tests.iOS.ps1 -CI
echo "status=success" >> $env:GITHUB_OUTPUT

- name: Upload test results on failure
if: ${{ failure() }}
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: testapp-ios-logs-${{ env.IOS_VERSION }}-${{ env.UNITY_VERSION }}-${{ env.INIT_TYPE }}
path: |
${{ env.ARTIFACTS_PATH }}
test/IntegrationTest/results/
retention-days: 14
6 changes: 6 additions & 0 deletions test/IntegrationTest/CommonTestCases.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ $CommonTestCases = @(
}
@{ Name = "Contains app context"; TestBlock = {
param($TestSetup, $TestType, $SentryEvent, $RunResult)

if ($TestType -eq "crash-capture" -and $TestSetup.Platform -eq "iOS") {
Set-ItResult -Skipped -Because "app context is not synced to sentry-cocoa on iOS"
return
}

$SentryEvent.contexts.app | Should -Not -BeNullOrEmpty
}
}
Expand Down
222 changes: 222 additions & 0 deletions test/IntegrationTest/Integration.Tests.iOS.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
#!/usr/bin/env pwsh
#
# Integration tests for Sentry Unity SDK (iOS Simulator)
#
# Environment variables:
# SENTRY_TEST_APP: path to the test .app bundle
# SENTRY_IOS_VERSION: iOS simulator version (e.g. "17.0" or "latest")
# SENTRY_TEST_DSN: test DSN
# SENTRY_AUTH_TOKEN: authentication token for Sentry API

Set-StrictMode -Version latest
$ErrorActionPreference = "Stop"

# Import app-runner modules
. $PSScriptRoot/../../modules/app-runner/import-modules.ps1

# Import shared test cases and utility functions
. $PSScriptRoot/CommonTestCases.ps1


BeforeAll {
$script:BundleId = "com.DefaultCompany.IntegrationTest"

# Run integration test action on device
function Invoke-TestAction {
param (
[Parameter(Mandatory=$true)]
[string]$Action
)

Write-Host "Running $Action..."

$appArgs = @("--test", $Action)

$runResult = Invoke-DeviceApp -ExecutablePath $script:BundleId -Arguments $appArgs

# Save result to JSON file
$runResult | ConvertTo-Json -Depth 5 | Out-File -FilePath (Get-OutputFilePath "${Action}-result.json")

# Launch app again to ensure crash report is sent
if ($Action -eq "crash-capture") {
Write-Host "Running crash-send to ensure crash report is sent..."

$sendArgs = @("--test", "crash-send")
$sendResult = Invoke-DeviceApp -ExecutablePath $script:BundleId -Arguments $sendArgs

# Save crash-send result to JSON for debugging
$sendResult | ConvertTo-Json -Depth 5 | Out-File -FilePath (Get-OutputFilePath "crash-send-result.json")

# Print crash-send output
Write-Host "::group::App output (crash-send)"
$sendResult.Output | ForEach-Object { Write-Host $_ }
Write-Host "::endgroup::"

# Attach to runResult for test access
$runResult | Add-Member -NotePropertyName "CrashSendOutput" -NotePropertyValue $sendResult.Output
}

# Print app output so it's visible in CI logs
Write-Host "::group::App output ($Action)"
$runResult.Output | ForEach-Object { Write-Host $_ }
Write-Host "::endgroup::"

return $runResult
}

# Create directory for the test results
New-Item -ItemType Directory -Path "$PSScriptRoot/results/" -ErrorAction Continue 2>&1 | Out-Null
Set-OutputDir -Path "$PSScriptRoot/results/"

# Initialize test parameters
$script:TestSetup = [PSCustomObject]@{
Platform = "iOS"
AppPath = $env:SENTRY_TEST_APP
iOSVersion = $env:SENTRY_IOS_VERSION
Dsn = $env:SENTRY_TEST_DSN
AuthToken = $env:SENTRY_AUTH_TOKEN
}

# Validate environment
if ([string]::IsNullOrEmpty($script:TestSetup.AppPath)) {
throw "SENTRY_TEST_APP environment variable is not set."
}
if (-not (Test-Path $script:TestSetup.AppPath)) {
throw "App not found at: $($script:TestSetup.AppPath)"
}
if ([string]::IsNullOrEmpty($script:TestSetup.iOSVersion)) {
throw "SENTRY_IOS_VERSION environment variable is not set."
}
if ([string]::IsNullOrEmpty($script:TestSetup.Dsn)) {
throw "SENTRY_TEST_DSN environment variable is not set."
}
if ([string]::IsNullOrEmpty($script:TestSetup.AuthToken)) {
throw "SENTRY_AUTH_TOKEN environment variable is not set."
}

Connect-SentryApi `
-ApiToken $script:TestSetup.AuthToken `
-DSN $script:TestSetup.Dsn

$target = $script:TestSetup.iOSVersion
# Convert bare version numbers (e.g. "17.0") to "iOS 17.0" format expected by iOSSimulatorProvider
if ($target -match '^\d+\.\d+$') {
$target = "iOS $target"
}
Connect-Device -Platform "iOSSimulator" -Target $target
Install-DeviceApp -Path $script:TestSetup.AppPath
}


AfterAll {
Disconnect-SentryApi
Disconnect-Device
}


Describe "Unity iOS Integration Tests" {

Context "Message Capture" {
BeforeAll {
$script:runEvent = $null
$script:runResult = Invoke-TestAction -Action "message-capture"

$eventId = Get-EventIds -AppOutput $script:runResult.Output -ExpectedCount 1
if ($eventId) {
Write-Host "::group::Getting event content"
$script:runEvent = Get-SentryTestEvent -EventId "$eventId"
Write-Host "::endgroup::"
}
}

It "<Name>" -ForEach $CommonTestCases {
& $testBlock -SentryEvent $runEvent -TestType "message-capture" -RunResult $runResult -TestSetup $script:TestSetup
}

It "Has message level info" {
($runEvent.tags | Where-Object { $_.key -eq "level" }).value | Should -Be "info"
}

It "Has message content" {
$runEvent.title | Should -Not -BeNullOrEmpty
}
}

Context "Exception Capture" {
BeforeAll {
$script:runEvent = $null
$script:runResult = Invoke-TestAction -Action "exception-capture"

$eventId = Get-EventIds -AppOutput $script:runResult.Output -ExpectedCount 1
if ($eventId) {
Write-Host "::group::Getting event content"
$script:runEvent = Get-SentryTestEvent -EventId "$eventId"
Write-Host "::endgroup::"
}
}

It "<Name>" -ForEach $CommonTestCases {
& $testBlock -SentryEvent $runEvent -TestType "exception-capture" -RunResult $runResult -TestSetup $script:TestSetup
}

It "Has exception information" {
$runEvent.exception | Should -Not -BeNullOrEmpty
$runEvent.exception.values | Should -Not -BeNullOrEmpty
}

It "Has exception with stacktrace" {
$exception = $runEvent.exception.values[0]
$exception | Should -Not -BeNullOrEmpty
$exception.type | Should -Not -BeNullOrEmpty
$exception.stacktrace | Should -Not -BeNullOrEmpty
}

It "Has error level" {
($runEvent.tags | Where-Object { $_.key -eq "level" }).value | Should -Be "error"
}
}

Context "Crash Capture" {
BeforeAll {
$script:runEvent = $null
$script:runResult = Invoke-TestAction -Action "crash-capture"

$eventId = Get-EventIds -AppOutput $script:runResult.Output -ExpectedCount 1
if ($eventId) {
Write-Host "::group::Getting event content"
$script:runEvent = Get-SentryTestEvent -TagName "test.crash_id" -TagValue "$eventId" -TimeoutSeconds 120
Write-Host "::endgroup::"
}
}

It "<Name>" -ForEach $CommonTestCases {
& $testBlock -SentryEvent $runEvent -TestType "crash-capture" -RunResult $runResult -TestSetup $script:TestSetup
}

It "Has fatal level" {
($runEvent.tags | Where-Object { $_.key -eq "level" }).value | Should -Be "fatal"
}

It "Has exception with stacktrace" {
$runEvent.exception | Should -Not -BeNullOrEmpty
$runEvent.exception.values | Should -Not -BeNullOrEmpty
$exception = $runEvent.exception.values[0]
$exception | Should -Not -BeNullOrEmpty
$exception.stacktrace | Should -Not -BeNullOrEmpty
}

It "Reports crashedLastRun as Crashed on relaunch" {
$crashedLastRunLine = $runResult.CrashSendOutput | Where-Object {
$_ -match "crashedLastRun=Crashed"
}
$crashedLastRunLine | Should -Not -BeNullOrEmpty -Because "Native SDK should report crashedLastRun=Crashed after a native crash"
}

It "Crash-send completes flush successfully" {
$flushLine = $runResult.CrashSendOutput | Where-Object {
$_ -match "Flush complete"
}
$flushLine | Should -Not -BeNullOrEmpty -Because "crash-send should complete its flush before quitting"
}
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Near-complete duplication of integration test file

Low Severity

Integration.Tests.iOS.ps1 is nearly identical to Integration.Tests.ps1 — the Describe block with all three test contexts (Message Capture, Exception Capture, Crash Capture) is copy-pasted verbatim. Only the BeforeAll setup (device connection, app launching via Invoke-TestAction) and the Describe title differ between the two files. This duplication means any future test-case additions or fixes need to be applied in both files, increasing the risk of drift. The shared test contexts could be extracted into a common helper (similar to CommonTestCases.ps1) to keep the platform-specific files focused on setup only.

Additional Locations (1)

Fix in Cursor Fix in Web

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 change: 1 addition & 0 deletions test/IntegrationTest/Integration.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ BeforeAll {

# Initialize test parameters
$script:TestSetup = [PSCustomObject]@{
Platform = "Android"
ApkPath = $env:SENTRY_TEST_APK
Dsn = $env:SENTRY_TEST_DSN
AuthToken = $env:SENTRY_AUTH_TOKEN
Expand Down
Loading