Skip to content

[dotnet test] Add androidtest project template and dotnet run instrumentation support#10862

Draft
jonathanpeppers wants to merge 10 commits intomainfrom
dev/peppers/androidtest
Draft

[dotnet test] Add androidtest project template and dotnet run instrumentation support#10862
jonathanpeppers wants to merge 10 commits intomainfrom
dev/peppers/androidtest

Conversation

@jonathanpeppers
Copy link
Member

Context: #10683

Add a new androidtest .NET project template that creates an Android test project using MSTest with Microsoft.Testing.Platform. The template includes a TestInstrumentation class that runs tests via am instrument and reports results (passed/failed/skipped) back through Android's instrumentation protocol.

Add --instrument option to Microsoft.Android.Run so dotnet run can launch test projects via am instrument -w instead of am start.

Fix an issue where NuGet packages like MSTest add assemblies as both properly-resolved publish assets (with DestinationSubPath metadata) and as None items (without DestinationSubPath) that flow into _SourceItemsToCopyToPublishDirectory. When NuGet conflict resolution arbitrarily picks the None-based copy, the assembly loses its DestinationSubPath and TargetPath metadata, causing it to either be missing from the APK or deployed to the wrong directory on device. The fix conditionally removes only items without DestinationSubPath, then re-adds any assemblies that were completely stripped with a cleared TargetPath so that downstream targets (ProcessAssemblies, FastDeploy) can set the correct per-architecture paths.

Changes:

  • New androidtest template under src/Microsoft.Android.Templates/
  • New GetAndroidInstrumentationName MSBuild task to resolve the instrumentation runner class from AndroidManifest.xml
  • Updated Microsoft.Android.Sdk.Application.targets to pass --instrument when EnableMSTestRunner is true
  • Added AdbHelper class to Microsoft.Android.Run for shared adb process management
  • Added --instrument CLI option to Microsoft.Android.Run/Program.cs
  • Fixed _ComputeFilesToPublishForRuntimeIdentifiers to preserve properly-resolved publish assets and recover missing assemblies
  • Added DotNetNewAndroidTest device integration test

TODO:

  • In a future PR, add support for dotnet test end-to-end.


static class AdbHelper
{
public static ProcessStartInfo CreateStartInfo (string adbPath, string? adbTarget, string arguments)
Copy link
Member

Choose a reason for hiding this comment

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

Does this make sense going to android-tools? and use that nupkg?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, we should open a PR here to test out any new Adb APIs from dotnet/android-tools. None are merged yet, right?

It would be proof the new APIs work, though.

…trumentation support

Context: #10683

Add a new `androidtest` .NET project template that creates an Android
test project using MSTest with Microsoft.Testing.Platform. The template
includes a TestInstrumentation class that runs tests via `am instrument`
and reports results (passed/failed/skipped) back through Android's
instrumentation protocol.

Add `--instrument` option to Microsoft.Android.Run so `dotnet run`
can launch test projects via `am instrument -w` instead of `am start`.

Fix an issue where NuGet packages like MSTest add assemblies as both
properly-resolved publish assets (with DestinationSubPath metadata) and
as None items (without DestinationSubPath) that flow into
`_SourceItemsToCopyToPublishDirectory`. When NuGet conflict resolution
arbitrarily picks the None-based copy, the assembly loses its
DestinationSubPath and TargetPath metadata, causing it to either be
missing from the APK or deployed to the wrong directory on device.
The fix conditionally removes only items without DestinationSubPath,
then re-adds any assemblies that were completely stripped with a cleared
TargetPath so that downstream targets (ProcessAssemblies, FastDeploy)
can set the correct per-architecture paths.

Changes:

- New `androidtest` template under src/Microsoft.Android.Templates/
- New GetAndroidInstrumentationName MSBuild task to resolve the
  instrumentation runner class from AndroidManifest.xml
- Updated Microsoft.Android.Sdk.Application.targets to pass
  `--instrument` when EnableMSTestRunner is true
- Added AdbHelper class to Microsoft.Android.Run for shared adb
  process management
- Added `--instrument` CLI option to Microsoft.Android.Run/Program.cs
- Fixed _ComputeFilesToPublishForRuntimeIdentifiers to preserve
  properly-resolved publish assets and recover missing assemblies
- Added DotNetNewAndroidTest device integration test

TODO:
- In a future PR, add support for `dotnet test` end-to-end.
@jonathanpeppers jonathanpeppers force-pushed the dev/peppers/androidtest branch from 16a61dc to f121c7c Compare March 6, 2026 22:28
jonathanpeppers and others added 3 commits March 6, 2026 16:36
Check pe.HasMetadata before calling GetMetadataReader() to avoid
InvalidOperationException when processing native DLLs (e.g. from
BenchmarkDotNet/TraceEvent NuGet packages) that don't have .NET
metadata.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jonathanpeppers added a commit to jonathanpeppers/iOSDotNetTest that referenced this pull request Mar 10, 2026
MSTest test platform assemblies fail AOT compilation because the IL linker
trims types (DoesNotReturnAttribute, MemberNotNullWhenAttribute) from
Microsoft.TestPlatform.CoreUtilities that are still referenced via custom
attributes in other test platform DLLs. Use MtouchInterpreter=all to bypass
AOT and run all assemblies through the interpreter instead.

See: dotnet/android#10862

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jonathanpeppers and others added 5 commits March 11, 2026 14:30
…tifiers

Compare by filename instead of full ItemSpec path when checking if
assemblies from _SourceItemsToCopyToPublishDirectory already exist in
ResolvedFileToPublish. Native DLLs like KernelTraceControl.dll (from
Microsoft.Diagnostics.Tracing.TraceEvent NuGet) can exist under
different paths, causing the old Remove-by-path to miss them and
re-add duplicates that crash GetPerArchAssemblies with XALNS7004.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…meIdentifiers

When _SourceItemsToCopyToPublishDirectory contains multiple items with the
same filename from different source paths (e.g., KernelTraceControl.dll),
_MissingAssemblyNames ends up with duplicate entries. These duplicates get
re-added to ResolvedFileToPublish, causing a Dictionary duplicate key error
in GetPerArchAssemblies (XALNS7004).

Use RemoveDuplicates task to deduplicate by filename before re-adding,
following the same pattern already used for NativeAOT deduplication.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
NuGet packages like microsoft.diagnostics.tracing.traceevent (a
dependency of BenchmarkDotNet) include native Windows DLLs under
lib/native/{arch}/ paths. These were flowing through
_SourceItemsToCopyToPublishDirectory into _MissingAssemblyNames and
being re-added to ResolvedFileToPublish. When the linker tried to
load them with Mono.Cecil, it threw BadImageFormatException
(XALNS7000/XA0009).

Filter out items whose OriginalItemSpec contains a /native/ path
segment, which covers both lib/native/ and runtimes/*/native/ NuGet
layout conventions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants