iOSDotNetTest
A prototype iOS "project template" for dotnet test.
See the Android equivalent here.
Usage
Run tests on the iOS simulator:
$ dotnet run
...
[PASSED] iOSDotNetTest.Test1.TestMethod1
[FAILED] iOSDotNetTest.Test1.TestMethod2
[SKIPPED] iOSDotNetTest.Test1.TestMethod3
Results: passed=1, failed=1, skipped=1
TRX report: /path/to/TestResults/_Machine_2026-03-10_19_51_43.trxThen collect the TRX results from the simulator:
$ dotnet build -t:GetResults
...
Test results copied to /path/to/TestResults/How It Works
The app uses UIApplication.Main() with an AppDelegate to establish a proper
UIKit run loop. This prevents iOS from watchdog-killing the app during long test
runs, which can happen when running tests directly from the entry point without
a UI run loop.
MSTest runs on a background thread from AppDelegate.FinishedLaunching().
A custom ResultConsumer logs per-test pass/fail/skip results to the console and
calls Environment.Exit() once the TRX report is written, signaling completion.
dotnet run handles the full build → install → launch cycle via the iOS
workload's built-in mlaunch integration. The GetResults MSBuild target uses
xcrun simctl to locate the app's data container and copy TRX files locally.
Why not XCTest?
Apple's native test infrastructure uses .xctest bundles — dynamic libraries
that xcodebuild test injects into a host app at runtime. We explored this
approach on the XCTestFramework
branch, but running tests from AppDelegate.FinishedLaunching() is the better
path for now because:
- New project type — the iOS workload would need to produce
.xctestbundles
(dylibs) instead of app executables, requiring a newOutputTypeand changes
to the native linking pipeline indotnet/macios. - Developer framework support —
Microsoft.iOSdoesn't ship bindings for
XCTest. It's a "developer only" framework not included in standard SDK search
paths, requiring custom linker flags (-F,-rpath) and either new bindings
or raw P/Invokes. - Two-project requirement — in Xcode, tests require both a host
.appand a
.xctestbundle as separate targets. This doesn't map to other .NET platforms
(Android, Windows) where a single test project is sufficient. - Unclear benefit — for running MSTest on a simulator, the main gain from
native.xctestsupport would be the ability to run tests inside app
extensions, bundles, or plugins. For the common case, the current approach
works just as well.
Workarounds
MtouchInterpreter=all: Disables AOT compilation and uses the interpreter
for all assemblies. MSTest platform DLLs have IL linker/AOT failures on iOS.GenerateTestingPlatformEntryPoint=false: MSTest SDK generates aMain()
method that conflicts with our top-level statements entry point.