Add FileLoggingProvider for MacCatalyst UI test logging#33518
Merged
Conversation
- Add FileLoggingProvider.cs: ILoggerProvider that writes to a file - Update MauiProgram.cs to add FileLoggingProvider when MAUI_LOG_FILE env var is set - Update UITest.cs to pass MAUI_LOG_FILE env var to app via Appium - Simplify BuildAndRunHostApp.ps1 to set MAUI_LOG_FILE directly to output path This enables capturing ILogger output (including framework errors) during MacCatalyst UI tests. The app writes logs directly to the specified file, which works even when Appium relaunches the app.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR adds a FileLoggingProvider to capture ILogger output during MacCatalyst UI tests, solving the problem where log messages were not being captured when Appium relaunches the app.
Changes:
- Implements a new
FileLoggingProviderclass that writes logs directly to a file specified via theMAUI_LOG_FILEenvironment variable - Updates
MauiProgram.csto register the file logging provider when the environment variable is set - Modifies
UITest.csto pass the log file path from environment to the app via Appium's environment arguments - Simplifies
BuildAndRunHostApp.ps1to set the environment variable directly instead of trying to capture stderr
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 10 comments.
| File | Description |
|---|---|
src/Controls/tests/TestCases.HostApp/FileLoggingProvider.cs |
New file implementing ILoggerProvider and ILogger for file-based logging with timestamps and log levels |
src/Controls/tests/TestCases.HostApp/MauiProgram.cs |
Adds FileLoggingProvider registration when MAUI_LOG_FILE environment variable is set |
src/Controls/tests/TestCases.Shared.Tests/UITest.cs |
Reads MAUI_LOG_FILE from environment and passes it to app via SetTestConfigurationArg |
.github/scripts/BuildAndRunHostApp.ps1 |
Sets MAUI_LOG_FILE environment variable for MacCatalyst and removes old stderr capture logic |
Comments suppressed due to low confidence (1)
.github/scripts/BuildAndRunHostApp.ps1:288
- The variable
$catalystAppProcessis initialized to$nullbut is never assigned a value in the updated code. The cleanup logic in the finally block (lines 279-288) checks if this variable is set and attempts to kill the process, but it will never execute because the variable remains null. This appears to be dead code left over from the previous implementation. Consider removing the unused variable and the unreachable cleanup code, or document why it's being kept for future use.
$catalystAppProcess = $null
if ($Platform -eq "catalyst") {
# Determine runtime identifier
$arch = [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture.ToString().ToLower()
$rid = if ($arch -eq "arm64") { "maccatalyst-arm64" } else { "maccatalyst-x64" }
# Build app path - matches Build-AndDeploy.ps1 output location
$appPath = Join-Path $PSScriptRoot "../../artifacts/bin/Controls.TestCases.HostApp/Debug/$TargetFramework/$rid/Controls.TestCases.HostApp.app"
$appPath = [System.IO.Path]::GetFullPath($appPath)
if (Test-Path $appPath) {
Write-Info "MacCatalyst app ready at: $appPath"
# Make executable (like CI does)
$executablePath = Join-Path $appPath "Contents/MacOS/Controls.TestCases.HostApp"
if (Test-Path $executablePath) {
& chmod +x $executablePath
}
Write-Success "MacCatalyst app prepared (Appium will launch with test name)"
} else {
Write-Warning "MacCatalyst app not found at: $appPath"
Write-Warning "Test may use wrong app bundle if another version is registered"
}
# Set log file path directly - app will write ILogger output here
$env:MAUI_LOG_FILE = $deviceLogFile
}
Write-Info "Executing: dotnet test --filter `"$effectiveFilter`""
Write-Host ""
try {
# Run dotnet test and capture output
$testOutput = & dotnet test $TestProject --filter $effectiveFilter --logger "console;verbosity=detailed" 2>&1
# Save test output to file
$testOutput | Out-File -FilePath $testOutputFile -Encoding UTF8
# Display test output
$testOutput | ForEach-Object { Write-Host $_ }
$testExitCode = $LASTEXITCODE
Write-Host ""
Write-Info "Test output saved to: $testOutputFile"
} catch {
Write-Error "Failed to run tests: $_"
exit 1
} finally {
# Stop MacCatalyst app process if we started it
if ($catalystAppProcess) {
# Re-fetch the process since the original reference may be stale
$runningApp = Get-Process -Id $catalystAppProcess.Id -ErrorAction SilentlyContinue
if ($runningApp -and -not $runningApp.HasExited) {
Write-Info "Stopping MacCatalyst app process (PID: $($catalystAppProcess.Id))..."
$runningApp.Kill()
$runningApp.WaitForExit(5000) | Out-Null
Write-Success "App process stopped"
}
}
3 tasks
- Fix XML doc comment: MAUI_ENABLE_FILE_LOGGING -> MAUI_LOG_FILE - Add Directory.CreateDirectory before StreamWriter for robustness - Change FileLoggingProvider and FileLogger to internal - Fix misleading comment: 'backward compatibility' -> 'local debugging visibility'
kubaflo
pushed a commit
to kubaflo/maui
that referenced
this pull request
Jan 16, 2026
> [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ## Description Adds a `FileLoggingProvider` to capture ILogger output during MacCatalyst UI tests. This solves the problem where Console.WriteLine and ILogger messages were not being captured when running UI tests via Appium. ### Problem When running MacCatalyst UI tests with `BuildAndRunHostApp.ps1`, log output was not being captured because: 1. Appium's Mac2 driver relaunches the app with `macos: launchApp` 2. This kills any existing app instance that had stderr capture configured 3. The new app instance launched by Appium has no logging connection to the test script ### Solution Instead of trying to capture stderr from outside the app, the app now writes its own logs to a file: 1. Test script sets `MAUI_LOG_FILE` environment variable to the desired log path 2. `UITest.cs` passes this env var to the app via Appium's environment args 3. `MauiProgram.cs` checks for the env var and adds `FileLoggingProvider` if set 4. App writes all ILogger output directly to the specified file 5. This works regardless of how the app is launched (directly or via Appium relaunch) ### Changes - **`FileLoggingProvider.cs`** (new): Simple `ILoggerProvider` implementation that writes formatted log messages to a file with timestamps and log levels - **`MauiProgram.cs`**: Adds `FileLoggingProvider` to logging pipeline when `MAUI_LOG_FILE` env var is set - **`UITest.cs`**: Reads `MAUI_LOG_FILE` from environment and passes it to app via `SetTestConfigurationArg` - **`BuildAndRunHostApp.ps1`**: Simplified - now just sets `MAUI_LOG_FILE` directly to output path instead of copying from temp file ### Usage ```powershell # Run MacCatalyst UI test with logging pwsh .github/scripts/BuildAndRunHostApp.ps1 -Platform catalyst -TestFilter "FullyQualifiedName~MyTest" # Logs are written directly to: # CustomAgentLogsTmp/UITests/catalyst-device.log ``` ### Example Log Output ``` === MAUI HostApp File Logger Started at 1/13/2026 2:29:21 PM === Log file: /path/to/catalyst-device.log Minimum log level: Debug [14:29:36.015] [ERROR] Microsoft.Maui.IApplication: Error Domain=UISceneErrorDomain Code=0 "The application does not support multiple scenes." Exception: Foundation.NSErrorException: Error Domain=UISceneErrorDomain Code=0 ... ```
simonrozsival
pushed a commit
that referenced
this pull request
Jan 16, 2026
> [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ## Description Adds a `FileLoggingProvider` to capture ILogger output during MacCatalyst UI tests. This solves the problem where Console.WriteLine and ILogger messages were not being captured when running UI tests via Appium. ### Problem When running MacCatalyst UI tests with `BuildAndRunHostApp.ps1`, log output was not being captured because: 1. Appium's Mac2 driver relaunches the app with `macos: launchApp` 2. This kills any existing app instance that had stderr capture configured 3. The new app instance launched by Appium has no logging connection to the test script ### Solution Instead of trying to capture stderr from outside the app, the app now writes its own logs to a file: 1. Test script sets `MAUI_LOG_FILE` environment variable to the desired log path 2. `UITest.cs` passes this env var to the app via Appium's environment args 3. `MauiProgram.cs` checks for the env var and adds `FileLoggingProvider` if set 4. App writes all ILogger output directly to the specified file 5. This works regardless of how the app is launched (directly or via Appium relaunch) ### Changes - **`FileLoggingProvider.cs`** (new): Simple `ILoggerProvider` implementation that writes formatted log messages to a file with timestamps and log levels - **`MauiProgram.cs`**: Adds `FileLoggingProvider` to logging pipeline when `MAUI_LOG_FILE` env var is set - **`UITest.cs`**: Reads `MAUI_LOG_FILE` from environment and passes it to app via `SetTestConfigurationArg` - **`BuildAndRunHostApp.ps1`**: Simplified - now just sets `MAUI_LOG_FILE` directly to output path instead of copying from temp file ### Usage ```powershell # Run MacCatalyst UI test with logging pwsh .github/scripts/BuildAndRunHostApp.ps1 -Platform catalyst -TestFilter "FullyQualifiedName~MyTest" # Logs are written directly to: # CustomAgentLogsTmp/UITests/catalyst-device.log ``` ### Example Log Output ``` === MAUI HostApp File Logger Started at 1/13/2026 2:29:21 PM === Log file: /path/to/catalyst-device.log Minimum log level: Debug [14:29:36.015] [ERROR] Microsoft.Maui.IApplication: Error Domain=UISceneErrorDomain Code=0 "The application does not support multiple scenes." Exception: Foundation.NSErrorException: Error Domain=UISceneErrorDomain Code=0 ... ```
simonrozsival
pushed a commit
that referenced
this pull request
Jan 16, 2026
> [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ## Description Adds a `FileLoggingProvider` to capture ILogger output during MacCatalyst UI tests. This solves the problem where Console.WriteLine and ILogger messages were not being captured when running UI tests via Appium. ### Problem When running MacCatalyst UI tests with `BuildAndRunHostApp.ps1`, log output was not being captured because: 1. Appium's Mac2 driver relaunches the app with `macos: launchApp` 2. This kills any existing app instance that had stderr capture configured 3. The new app instance launched by Appium has no logging connection to the test script ### Solution Instead of trying to capture stderr from outside the app, the app now writes its own logs to a file: 1. Test script sets `MAUI_LOG_FILE` environment variable to the desired log path 2. `UITest.cs` passes this env var to the app via Appium's environment args 3. `MauiProgram.cs` checks for the env var and adds `FileLoggingProvider` if set 4. App writes all ILogger output directly to the specified file 5. This works regardless of how the app is launched (directly or via Appium relaunch) ### Changes - **`FileLoggingProvider.cs`** (new): Simple `ILoggerProvider` implementation that writes formatted log messages to a file with timestamps and log levels - **`MauiProgram.cs`**: Adds `FileLoggingProvider` to logging pipeline when `MAUI_LOG_FILE` env var is set - **`UITest.cs`**: Reads `MAUI_LOG_FILE` from environment and passes it to app via `SetTestConfigurationArg` - **`BuildAndRunHostApp.ps1`**: Simplified - now just sets `MAUI_LOG_FILE` directly to output path instead of copying from temp file ### Usage ```powershell # Run MacCatalyst UI test with logging pwsh .github/scripts/BuildAndRunHostApp.ps1 -Platform catalyst -TestFilter "FullyQualifiedName~MyTest" # Logs are written directly to: # CustomAgentLogsTmp/UITests/catalyst-device.log ``` ### Example Log Output ``` === MAUI HostApp File Logger Started at 1/13/2026 2:29:21 PM === Log file: /path/to/catalyst-device.log Minimum log level: Debug [14:29:36.015] [ERROR] Microsoft.Maui.IApplication: Error Domain=UISceneErrorDomain Code=0 "The application does not support multiple scenes." Exception: Foundation.NSErrorException: Error Domain=UISceneErrorDomain Code=0 ... ```
simonrozsival
pushed a commit
that referenced
this pull request
Jan 20, 2026
> [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ## Description Adds a `FileLoggingProvider` to capture ILogger output during MacCatalyst UI tests. This solves the problem where Console.WriteLine and ILogger messages were not being captured when running UI tests via Appium. ### Problem When running MacCatalyst UI tests with `BuildAndRunHostApp.ps1`, log output was not being captured because: 1. Appium's Mac2 driver relaunches the app with `macos: launchApp` 2. This kills any existing app instance that had stderr capture configured 3. The new app instance launched by Appium has no logging connection to the test script ### Solution Instead of trying to capture stderr from outside the app, the app now writes its own logs to a file: 1. Test script sets `MAUI_LOG_FILE` environment variable to the desired log path 2. `UITest.cs` passes this env var to the app via Appium's environment args 3. `MauiProgram.cs` checks for the env var and adds `FileLoggingProvider` if set 4. App writes all ILogger output directly to the specified file 5. This works regardless of how the app is launched (directly or via Appium relaunch) ### Changes - **`FileLoggingProvider.cs`** (new): Simple `ILoggerProvider` implementation that writes formatted log messages to a file with timestamps and log levels - **`MauiProgram.cs`**: Adds `FileLoggingProvider` to logging pipeline when `MAUI_LOG_FILE` env var is set - **`UITest.cs`**: Reads `MAUI_LOG_FILE` from environment and passes it to app via `SetTestConfigurationArg` - **`BuildAndRunHostApp.ps1`**: Simplified - now just sets `MAUI_LOG_FILE` directly to output path instead of copying from temp file ### Usage ```powershell # Run MacCatalyst UI test with logging pwsh .github/scripts/BuildAndRunHostApp.ps1 -Platform catalyst -TestFilter "FullyQualifiedName~MyTest" # Logs are written directly to: # CustomAgentLogsTmp/UITests/catalyst-device.log ``` ### Example Log Output ``` === MAUI HostApp File Logger Started at 1/13/2026 2:29:21 PM === Log file: /path/to/catalyst-device.log Minimum log level: Debug [14:29:36.015] [ERROR] Microsoft.Maui.IApplication: Error Domain=UISceneErrorDomain Code=0 "The application does not support multiple scenes." Exception: Foundation.NSErrorException: Error Domain=UISceneErrorDomain Code=0 ... ```
This was referenced Feb 12, 2026
Merged
Closed
Merged
Merged
This was referenced Feb 16, 2026
Open
Open
Open
Closed
Open
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Note
Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!
Description
Adds a
FileLoggingProviderto capture ILogger output during MacCatalyst UI tests. This solves the problem where Console.WriteLine and ILogger messages were not being captured when running UI tests via Appium.Problem
When running MacCatalyst UI tests with
BuildAndRunHostApp.ps1, log output was not being captured because:macos: launchAppSolution
Instead of trying to capture stderr from outside the app, the app now writes its own logs to a file:
MAUI_LOG_FILEenvironment variable to the desired log pathUITest.cspasses this env var to the app via Appium's environment argsMauiProgram.cschecks for the env var and addsFileLoggingProviderif setChanges
FileLoggingProvider.cs(new): SimpleILoggerProviderimplementation that writes formatted log messages to a file with timestamps and log levelsMauiProgram.cs: AddsFileLoggingProviderto logging pipeline whenMAUI_LOG_FILEenv var is setUITest.cs: ReadsMAUI_LOG_FILEfrom environment and passes it to app viaSetTestConfigurationArgBuildAndRunHostApp.ps1: Simplified - now just setsMAUI_LOG_FILEdirectly to output path instead of copying from temp fileUsage
Example Log Output