Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), testAsset.props))\testAsset.props" />

<PropertyGroup>
<TargetFramework>$(CurrentTargetFramework)</TargetFramework>
<OutputType>Exe</OutputType>

<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<GenerateProgramFile>false</GenerateProgramFile>
<ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally>
<IsTestingPlatformApplication>true</IsTestingPlatformApplication>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Testing.Platform" Version="$(MicrosoftTestingPlatformVersion)" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using System.Reflection;
using Microsoft.Testing.Platform.Builder;
using Microsoft.Testing.Platform.Capabilities.TestFramework;
using Microsoft.Testing.Platform.Extensions.Messages;
using Microsoft.Testing.Platform.Extensions.TestFramework;

// Drop a uniquely-named marker file per process launch so tests can deterministically count how many
// times this test application actually ran (used to validate traversal de-duplication).
var markerDir = Environment.GetEnvironmentVariable("TRAVERSAL_MARKER_DIR");
if (!string.IsNullOrEmpty(markerDir))
{
Directory.CreateDirectory(markerDir);
var assemblyName = Assembly.GetEntryAssembly()?.GetName().Name ?? "unknown";
File.WriteAllText(Path.Combine(markerDir, $"{assemblyName}-{Guid.NewGuid():N}.marker"), assemblyName);
}

var testApplicationBuilder = await TestApplication.CreateBuilderAsync(args);

testApplicationBuilder.RegisterTestFramework(_ => new TestFrameworkCapabilities(), (_, __) => new DummyTestAdapter());

using var testApplication = await testApplicationBuilder.BuildAsync();
return await testApplication.RunAsync();

public class DummyTestAdapter : ITestFramework, IDataProducer
{
public string Uid => nameof(DummyTestAdapter);

public string Version => "2.0.0";

public string DisplayName => nameof(DummyTestAdapter);

public string Description => nameof(DummyTestAdapter);

public Task<bool> IsEnabledAsync() => Task.FromResult(true);

public Type[] DataTypesProduced => [];

public Task<CreateTestSessionResult> CreateTestSessionAsync(CreateTestSessionContext context)
=> Task.FromResult(new CreateTestSessionResult() { IsSuccess = true });

public Task<CloseTestSessionResult> CloseTestSessionAsync(CloseTestSessionContext context)
=> Task.FromResult(new CloseTestSessionResult() { IsSuccess = true });

public async Task ExecuteRequestAsync(ExecuteRequestContext context)
{
context.Complete();
await Task.CompletedTask;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), testAsset.props))\testAsset.props" />

<PropertyGroup>
<TargetFramework>$(CurrentTargetFramework)</TargetFramework>
<OutputType>Exe</OutputType>

<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<GenerateProgramFile>false</GenerateProgramFile>
<ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally>
<IsTestingPlatformApplication>true</IsTestingPlatformApplication>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Testing.Platform" Version="$(MicrosoftTestingPlatformVersion)" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using System.Reflection;
using Microsoft.Testing.Platform.Builder;
using Microsoft.Testing.Platform.Capabilities.TestFramework;
using Microsoft.Testing.Platform.Extensions.Messages;
using Microsoft.Testing.Platform.Extensions.TestFramework;

// Drop a uniquely-named marker file per process launch so tests can deterministically count how many
// times this test application actually ran (used to validate traversal de-duplication).
var markerDir = Environment.GetEnvironmentVariable("TRAVERSAL_MARKER_DIR");
if (!string.IsNullOrEmpty(markerDir))
{
Directory.CreateDirectory(markerDir);
var assemblyName = Assembly.GetEntryAssembly()?.GetName().Name ?? "unknown";
File.WriteAllText(Path.Combine(markerDir, $"{assemblyName}-{Guid.NewGuid():N}.marker"), assemblyName);
}

var testApplicationBuilder = await TestApplication.CreateBuilderAsync(args);

testApplicationBuilder.RegisterTestFramework(_ => new TestFrameworkCapabilities(), (_, __) => new DummyTestAdapter());

using var testApplication = await testApplicationBuilder.BuildAsync();
return await testApplication.RunAsync();

public class DummyTestAdapter : ITestFramework, IDataProducer
{
public string Uid => nameof(DummyTestAdapter);

public string Version => "2.0.0";

public string DisplayName => nameof(DummyTestAdapter);

public string Description => nameof(DummyTestAdapter);

public Task<bool> IsEnabledAsync() => Task.FromResult(true);

public Type[] DataTypesProduced => [];

public Task<CreateTestSessionResult> CreateTestSessionAsync(CreateTestSessionContext context)
=> Task.FromResult(new CreateTestSessionResult() { IsSuccess = true });

public Task<CloseTestSessionResult> CloseTestSessionAsync(CloseTestSessionContext context)
=> Task.FromResult(new CloseTestSessionResult() { IsSuccess = true });

public async Task ExecuteRequestAsync(ExecuteRequestContext context)
{
context.Complete();
await Task.CompletedTask;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), testAsset.props))\testAsset.props" />

<PropertyGroup>
<TargetFramework>$(CurrentTargetFramework)</TargetFramework>
<OutputType>Exe</OutputType>

<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<GenerateProgramFile>false</GenerateProgramFile>
<ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally>
<IsTestingPlatformApplication>true</IsTestingPlatformApplication>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Testing.Platform" Version="$(MicrosoftTestingPlatformVersion)" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using System.Reflection;
using Microsoft.Testing.Platform.Builder;
using Microsoft.Testing.Platform.Capabilities.TestFramework;
using Microsoft.Testing.Platform.Extensions.Messages;
using Microsoft.Testing.Platform.Extensions.TestFramework;

// Drop a uniquely-named marker file per process launch so tests can deterministically count how many
// times this test application actually ran (used to validate traversal de-duplication).
var markerDir = Environment.GetEnvironmentVariable("TRAVERSAL_MARKER_DIR");
if (!string.IsNullOrEmpty(markerDir))
{
Directory.CreateDirectory(markerDir);
var assemblyName = Assembly.GetEntryAssembly()?.GetName().Name ?? "unknown";
File.WriteAllText(Path.Combine(markerDir, $"{assemblyName}-{Guid.NewGuid():N}.marker"), assemblyName);
}

var testApplicationBuilder = await TestApplication.CreateBuilderAsync(args);

testApplicationBuilder.RegisterTestFramework(_ => new TestFrameworkCapabilities(), (_, __) => new DummyTestAdapter());

using var testApplication = await testApplicationBuilder.BuildAsync();
return await testApplication.RunAsync();

public class DummyTestAdapter : ITestFramework, IDataProducer
{
public string Uid => nameof(DummyTestAdapter);

public string Version => "2.0.0";

public string DisplayName => nameof(DummyTestAdapter);

public string Description => nameof(DummyTestAdapter);

public Task<bool> IsEnabledAsync() => Task.FromResult(true);

public Type[] DataTypesProduced => [];

public Task<CreateTestSessionResult> CreateTestSessionAsync(CreateTestSessionContext context)
=> Task.FromResult(new CreateTestSessionResult() { IsSuccess = true });

public Task<CloseTestSessionResult> CloseTestSessionAsync(CloseTestSessionContext context)
=> Task.FromResult(new CloseTestSessionResult() { IsSuccess = true });

public async Task ExecuteRequestAsync(ExecuteRequestContext context)
{
context.Complete();
await Task.CompletedTask;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace NonTestLibrary;

// A plain (non-test) class library referenced by a nested traversal project.
// dotnet test must silently skip it: it is neither IsTestProject nor
// IsTestingPlatformApplication, so it produces no test module and no error.
public static class Class1
{
public static int Add(int a, int b) => a + b;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), testAsset.props))\testAsset.props" />

<PropertyGroup>
<TargetFramework>$(CurrentTargetFramework)</TargetFramework>

<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally>
</PropertyGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<Project Sdk="Microsoft.Build.Traversal/4.1.82">
<ItemGroup>
<!-- Level 0 (top): a test project plus a nested traversal project. -->
<ProjectReference Include="Level1TestProject\Level1TestProject.csproj" />
<ProjectReference Include="level2\dirs.proj" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"test": {
"runner": "Microsoft.Testing.Platform"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.Build.Traversal/4.1.82">
<ItemGroup>
<!-- Level 1: a test project, a non-test class library (must be silently skipped),
and a deeper nested traversal project. -->
<ProjectReference Include="..\Level2TestProject\Level2TestProject.csproj" />
<ProjectReference Include="..\NonTestLibrary\NonTestLibrary.csproj" />
<ProjectReference Include="level3\dirs.proj" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<Project Sdk="Microsoft.Build.Traversal/4.1.82">
<ItemGroup>
<!-- Level 2 (deepest): a test project reachable only through three levels of traversal. -->
<ProjectReference Include="..\..\DeepLeafTestProject\DeepLeafTestProject.csproj" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,39 @@ public void RunNestedTraversalProjectWithDiamond_ShouldRunSharedProjectOnce(stri
result.ExitCode.Should().Be(ExitCodes.ZeroTests);
}

[DataRow(TestingConstants.Debug)]
[DataRow(TestingConstants.Release)]
[TestMethod]
public void RunDeeplyNestedTraversalProject_ShouldRunEveryReferencedTestProjectAndSkipNonTestProjects(string configuration)
{
TestAsset testInstance = TestAssetsManager.CopyTestAsset("TraversalTestProjectsDeepNested", Guid.NewGuid().ToString())
.WithSource();

// Each test-host launch drops a uniquely-named marker file, giving a deterministic count of
// how many times each referenced project actually ran.
string markerDir = Path.Combine(testInstance.Path, "run-markers");

CommandResult result = new DotnetTestCommand(Log, disableNewOutput: false)
.WithWorkingDirectory(testInstance.Path)
.WithEnvironmentVariable("TRAVERSAL_MARKER_DIR", markerDir)
.Execute("dirs.proj", "-c", configuration);

// The graph is three levels deep: dirs.proj -> level2\dirs.proj -> level2\level3\dirs.proj.
// A test project is referenced at each level; all must run exactly once (proving deep recursion).
int MarkerCount(string project) => Directory.Exists(markerDir) ? Directory.GetFiles(markerDir, $"{project}-*.marker").Length : 0;

MarkerCount("Level1TestProject").Should().Be(1);
MarkerCount("Level2TestProject").Should().Be(1);
MarkerCount("DeepLeafTestProject").Should().Be(1);

// NonTestLibrary is a plain class library referenced by the level-2 traversal. It is neither a
// test project nor an MTP application, so it must be silently skipped: it never runs and does not
// cause an error.
MarkerCount("NonTestLibrary").Should().Be(0);

result.ExitCode.Should().Be(ExitCodes.ZeroTests);
}

[DataRow(TestingConstants.Debug)]
[DataRow(TestingConstants.Release)]
[TestMethod]
Expand Down
Loading