Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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/integration-test-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
SENTRY_UNREAL_TEST_APP_PATH: ${{ github.workspace }}/sample-build/SentryPlayground.sh
run: |
cmake -B build -S .
Invoke-Pester Integration.Tests.ps1 -CI
Invoke-Pester Integration.Desktop.Tests.ps1 -CI

- name: Upload integration test output
if: ${{ always() && steps.run-integration-tests.outcome == 'failure' }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/integration-test-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
SENTRY_UNREAL_TEST_APP_PATH: ${{ github.workspace }}/sample-build/SentryPlayground.exe
run: |
cmake -B build -S .
Invoke-Pester Integration.Tests.ps1 -CI
Invoke-Pester Integration.Desktop.Tests.ps1 -CI

- name: Upload integration test output
if: ${{ always() && steps.run-integration-tests.outcome == 'failure' }}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,72 +1,50 @@
# Integration tests for Sentry Unreal SDK
# Integration tests for Sentry Unreal SDK on desktop platforms
#
# Usage:
# Invoke-Pester Integration.Desktop.Tests.ps1
#
# Requires:
# - Pre-built SentryPlayground application
# - Environment variables: SENTRY_UNREAL_TEST_DSN, SENTRY_AUTH_TOKEN, SENTRY_UNREAL_TEST_APP_PATH

Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'

function script:Invoke-SentryUnrealTestApp {
[CmdletBinding()]
param(
[Parameter(Mandatory)]
[string[]]$Arguments,

[Parameter(Mandatory)]
[string]$TestName,

[Parameter()]
[int]$TimeoutSeconds = 300
)

# Generate timestamp and output file paths
$timestamp = Get-Date -Format 'yyyyMMdd-HHmmss'
$stdoutFile = "$script:OutputDir/$timestamp-$TestName-stdout.log"
$stderrFile = "$script:OutputDir/$timestamp-$TestName-stderr.log"
$resultFile = "$script:OutputDir/$timestamp-$TestName-result.json"

$exitCode = -1

try {
$process = Start-Process -FilePath $script:AppPath -ArgumentList $Arguments `
-PassThru -NoNewWindow `
-RedirectStandardOutput $stdoutFile `
-RedirectStandardError $stderrFile

if ($process.WaitForExit($TimeoutSeconds * 1000)) {
$exitCode = $process.ExitCode
} else {
Write-Host "Process timed out after $TimeoutSeconds seconds. Killing process..." -ForegroundColor Red
$process.Kill($true)
$exitCode = -1
BeforeDiscovery {
# Detect current platform and add as test target
function Get-CurrentDesktopPlatform {
if ($IsWindows) {
return 'Windows'
}
elseif ($IsMacOS) {
return 'MacOS'
}
elseif ($IsLinux) {
return 'Linux'
}
else {
return $null
}
} catch {
Write-Host "Process execution failed: $_" -ForegroundColor Red
$exitCode = -1
}

# Read output from files to ensure we get everything that was written
$stdout = @()
$stderr = @()

if (Test-Path $stdoutFile) {
$stdout = Get-Content $stdoutFile -ErrorAction SilentlyContinue
}

if (Test-Path $stderrFile) {
$stderr = Get-Content $stderrFile -ErrorAction SilentlyContinue
}
# Define test targets
function Get-TestTarget {
param(
[string]$Platform,
[string]$ProviderName
)

$result = @{
ExitCode = $exitCode
Output = $stdout
Error = $stderr
return @{
Platform = $Platform
ProviderName = $ProviderName
}
}

# Save full output to result JSON
$result | ConvertTo-Json -Depth 10 | Out-File $resultFile

return $result
# Only test the current desktop platform
$TestTargets = @()
$currentPlatform = Get-CurrentDesktopPlatform
$currentPlatform | Should -Not -Be $null
$TestTargets += Get-TestTarget -Platform $currentPlatform -ProviderName $currentPlatform
}

BeforeAll {
Expand Down Expand Up @@ -99,23 +77,37 @@ BeforeAll {
throw "Environment variable SENTRY_UNREAL_TEST_APP_PATH must be set"
}

# Connect to Sentry API
Write-Host "Connecting to Sentry API..." -ForegroundColor Yellow
Connect-SentryApi -DSN $script:DSN -ApiToken $script:AuthToken

# Validate app path
if (-not (Test-Path $script:AppPath)) {
throw "Application not found at: $script:AppPath"
}

# 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
}
}

Describe "Sentry Unreal Integration Tests" {
Describe "Sentry Unreal Desktop Integration Tests (<Platform>)" -ForEach $TestTargets {

BeforeAll {
# Connect to desktop device (required to create corresponding provider)
Write-Host "Connecting to $Platform..." -ForegroundColor Yellow
Connect-Device -Platform $Platform
}

AfterAll {
# Disconnect from desktop device
Write-Host "Disconnecting from $Platform..." -ForegroundColor Yellow
Disconnect-Device

Write-Host "Integration tests complete on $Platform" -ForegroundColor Green
}

Context "Crash Capture Tests" {
BeforeAll {
Expand All @@ -126,12 +118,19 @@ Describe "Sentry Unreal Integration Tests" {

# Build arguments and execute application:
# -crash-capture: Triggers integration test crash scenario in the sample app
# -init-only: Only initializes the app to flush captured events and quit right after
# -nullrhi: Runs without graphics rendering (headless mode)
# -unattended: Disables user prompts and interactive dialogs
# -stdout: Ensures logs are written to stdout on Linux/Unix systems
# -nosplash: Prevents splash screen and dialogs
$appArgs = @('-crash-capture', '-nullrhi', '-unattended', '-stdout', '-nosplash')
$script:CrashResult = Invoke-SentryUnrealTestApp -Arguments $appArgs -TestName 'crash'
$appArgs = @('-nullrhi', '-unattended', '-stdout', '-nosplash')
$script:CrashResult = Invoke-DeviceApp -ExecutablePath $script:AppPath -Arguments (@('-crash-capture') + $appArgs -join ' ')

# On macOS, the crash is captured but not uploaded immediately (due to Cocoa’s behavior),
# so we need to run the test app again to send it to Sentry
if ($Platform -eq 'MacOS') {
Invoke-DeviceApp -ExecutablePath $script:AppPath -Arguments (@('-init-only') + $appArgs -join ' ')
}

Write-Host "Crash test executed. Exit code: $($script:CrashResult.ExitCode)" -ForegroundColor Cyan

Expand All @@ -147,10 +146,12 @@ Describe "Sentry Unreal Integration Tests" {
try {
$script:CrashEvent = Get-SentryTestEvent -TagName 'test.crash_id' -TagValue "$crashId"
Write-Host "Event fetched from Sentry successfully" -ForegroundColor Green
} catch {
}
catch {
Write-Host "Failed to fetch event from Sentry: $_" -ForegroundColor Red
}
} else {
}
else {
Write-Host "Warning: No event ID found in output" -ForegroundColor Yellow
}
}
Expand All @@ -171,7 +172,12 @@ Describe "Sentry Unreal Integration Tests" {

It "Should have correct event type and platform" {
$script:CrashEvent.type | Should -Be 'error'
$script:CrashEvent.platform | Should -Be 'native'
if ($Platform -eq 'MacOS') {
$script:CrashEvent.platform | Should -Be 'cocoa'
}
else {
$script:CrashEvent.platform | Should -Be 'native'
}
}

It "Should have exception information" {
Expand Down Expand Up @@ -217,7 +223,7 @@ Describe "Sentry Unreal Integration Tests" {
# -stdout: Ensures logs are written to stdout on Linux/Unix systems
# -nosplash: Prevents splash screen and dialogs
$appArgs = @('-message-capture', '-nullrhi', '-unattended', '-stdout', '-nosplash')
$script:MessageResult = Invoke-SentryUnrealTestApp -Arguments $appArgs -TestName 'message'
$script:MessageResult = Invoke-DeviceApp -ExecutablePath $script:AppPath -Arguments ($appArgs -join ' ')

Write-Host "Message test executed. Exit code: $($script:MessageResult.ExitCode)" -ForegroundColor Cyan

Expand All @@ -231,10 +237,12 @@ Describe "Sentry Unreal Integration Tests" {
try {
$script:MessageEvent = Get-SentryTestEvent -EventId $eventIds[0]
Write-Host "Event fetched from Sentry successfully" -ForegroundColor Green
} catch {
}
catch {
Write-Host "Failed to fetch event from Sentry: $_" -ForegroundColor Red
}
} else {
}
else {
Write-Host "Warning: No event ID found in output" -ForegroundColor Yellow
}
}
Expand All @@ -260,7 +268,12 @@ Describe "Sentry Unreal Integration Tests" {
}

It "Should have correct platform" {
$script:MessageEvent.platform | Should -Be 'native'
if ($Platform -eq 'MacOS') {
$script:MessageEvent.platform | Should -Be 'cocoa'
}
else {
$script:MessageEvent.platform | Should -Be 'native'
}
}

It "Should have message content" {
Expand Down Expand Up @@ -288,5 +301,6 @@ Describe "Sentry Unreal Integration Tests" {
AfterAll {
Write-Host "Disconnecting from Sentry API..." -ForegroundColor Yellow
Disconnect-SentryApi

Write-Host "Integration tests complete" -ForegroundColor Green
}
8 changes: 4 additions & 4 deletions integration-test/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ $env:SENTRY_UNREAL_TEST_APP_PATH = "path/to/SentryPlayground.exe"

# Run tests
cd integration-test
Invoke-Pester Integration.Tests.ps1
Invoke-Pester Integration.Desktop.Tests.ps1
```

### Linux
Expand All @@ -104,7 +104,7 @@ export SENTRY_UNREAL_TEST_APP_PATH="./path/to/SentryPlayground.sh"

# Run tests
cd integration-test
pwsh -Command "Invoke-Pester Integration.Tests.ps1"
pwsh -Command "Invoke-Pester Integration.Desktop.Tests.ps1"
```

### Android
Expand Down Expand Up @@ -136,7 +136,7 @@ Invoke-Pester Integration.Android.Tests.ps1

The integration tests cover:

### Crash Capture Tests _(Windows/Linux)_
### Crash Capture Tests
- Application crashes with non-zero exit code
- Event ID is captured from output (set via `test.crash_id` tag)
- Crash event appears in Sentry
Expand All @@ -148,7 +148,7 @@ The integration tests cover:

**Note**: Crash capture tests are currently disabled on Android due to a known issue with tag persistence across app sessions.

### Message Capture Tests _(All platforms)_
### Message Capture Tests
- Application exits cleanly (exit code 0 on Windows/Linux, Android doesn't report exit codes)
- Event ID is captured from output
- TEST_RESULT indicates success
Expand Down
15 changes: 11 additions & 4 deletions sample/Source/SentryPlayground/SentryPlaygroundGameInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ void USentryPlaygroundGameInstance::Init()
// Check for expected test parameters to decide between running integration tests
// or launching the sample app with UI for manual testing
if (FParse::Param(*CommandLine, TEXT("crash-capture")) ||
FParse::Param(*CommandLine, TEXT("message-capture")))
FParse::Param(*CommandLine, TEXT("message-capture")) ||
FParse::Param(*CommandLine, TEXT("init-only")))
{
RunIntegrationTest(CommandLine);
}
Expand Down Expand Up @@ -74,6 +75,10 @@ void USentryPlaygroundGameInstance::RunIntegrationTest(const FString& CommandLin
{
RunMessageTest();
}
else if (FParse::Param(*CommandLine, TEXT("init-only")))
{
CompleteTestWithResult(TEXT("init-only"), true, TEXT("Test complete"));
}
}

void USentryPlaygroundGameInstance::RunCrashTest()
Expand Down Expand Up @@ -110,9 +115,6 @@ void USentryPlaygroundGameInstance::RunMessageTest()
UE_LOG(LogSentrySample, Display, TEXT("EVENT_CAPTURED: %s\n"), *FormatEventIdWithHyphens(EventId));
#endif

// Ensure events were flushed
SentrySubsystem->Close();

CompleteTestWithResult(TEXT("message-capture"), !EventId.IsEmpty(), TEXT("Test complete"));
}

Expand All @@ -133,6 +135,11 @@ void USentryPlaygroundGameInstance::ConfigureTestContext()

void USentryPlaygroundGameInstance::CompleteTestWithResult(const FString& TestName, bool Result, const FString& Message)
{
USentrySubsystem* SentrySubsystem = GEngine->GetEngineSubsystem<USentrySubsystem>();

// Ensure events were flushed
SentrySubsystem->Close();

UE_LOG(LogSentrySample, Display, TEXT("TEST_RESULT: {\"test\":\"%s\",\"success\":%s,\"message\":\"%s\"}\n"),
*TestName, Result ? TEXT("true") : TEXT("false"), *Message);

Expand Down
Loading