AOP for MSTest
This is how you can use MSTest .
The code that you start with is
<!-- file: UnitTestProject1.csproj -->
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<OutputType>exe</OutputType>
<PublishAot>true</PublishAot>
</PropertyGroup>
<ItemGroup>
<!--
Experimental MSTest Engine & source generator,
close sourced, licensed the same as our extensions
with Microsoft Testing Platform Tools license.
-->
<PackageReference Include="MSTest.Engine" Version="1.0.0-alpha.24163.4" />
<PackageReference Include="MSTest.SourceGeneration" Version="1.0.0-alpha.24163.4" />
<PackageReference Include="Microsoft.CodeCoverage.MSBuild" Version="17.10.4" />
<PackageReference Include="Microsoft.Testing.Extensions.CodeCoverage" Version="17.10.4" />
<PackageReference Include="Microsoft.Testing.Extensions.TrxReport" Version="1.0.2" />
<PackageReference Include="Microsoft.Testing.Platform.MSBuild" Version="1.0.2" />
<PackageReference Include="MSTest.TestFramework" Version="3.2.2" />
<PackageReference Include="MSTest.Analyzers" Version="3.2.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MyImportantClass\MyImportantClass.csproj" />
</ItemGroup>
<ItemGroup>
<Using Include="Microsoft.VisualStudio.TestTools.UnitTesting" />
</ItemGroup>
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
</PropertyGroup>
</Project>
The code that you will use is
// file: UnitTest1.cs
using MyImportantClass;
namespace DemoTest;
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
Assert.AreEqual(3, new Class1().Add(1, 2));
}
[TestMethod]
[DataRow(1, 2)]
[DataRow(100, -97)]
public void TestMethod2(int left, int right)
{
Assert.AreEqual(3, new Class1().Add(left, right));
}
}
The code that is generated is
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by Microsoft Testing Framework Generator.
// </auto-generated>
//------------------------------------------------------------------------------
namespace DemoTest
{
using Threading = global::System.Threading;
using ColGen = global::System.Collections.Generic;
using CA = global::System.Diagnostics.CodeAnalysis;
using Sys = global::System;
using Msg = global::Microsoft.Testing.Platform.Extensions.Messages;
using MSTF = global::Microsoft.Testing.Framework;
[CA::ExcludeFromCodeCoverage]
public static class DemoTest_UnitTest1
{
public static readonly MSTF::TestNode TestNode = new MSTF::TestNode
{
StableUid = "DemoTest.DemoTest.UnitTest1",
DisplayName = "UnitTest1",
Properties = new Msg::IProperty[1]
{
new Msg::TestFileLocationProperty(@"D:\gth\RSCG_Examples\v2\rscg_examples\MSTest\src\DemoTest\UnitTest1.cs", new(new(6, -1), new(22, -1))),
},
Tests = new MSTF::TestNode[]
{
new MSTF::InternalUnsafeActionTestNode
{
StableUid = "DemoTest.DemoTest.UnitTest1.TestMethod1()",
DisplayName = "TestMethod1",
Properties = new Msg::IProperty[2]
{
new Msg::TestMethodIdentifierProperty(
"DemoTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
"DemoTest",
"UnitTest1",
"TestMethod1",
Sys::Array.Empty<string>(),
"System.Void"),
new Msg::TestFileLocationProperty(@"D:\gth\RSCG_Examples\v2\rscg_examples\MSTest\src\DemoTest\UnitTest1.cs", new(new(9, -1), new(13, -1))),
},
Body = static testExecutionContext =>
{
var instance = new UnitTest1();
try
{
instance.TestMethod1();
}
catch (global::System.Exception ex)
{
testExecutionContext.ReportException(ex, null);
}
},
},
new MSTF::InternalUnsafeActionParameterizedTestNode<MSTF::InternalUnsafeTestArgumentsEntry<(int left, int right)>>
{
StableUid = "DemoTest.DemoTest.UnitTest1.TestMethod2(int, int)",
DisplayName = "TestMethod2",
Properties = new Msg::IProperty[2]
{
new Msg::TestMethodIdentifierProperty(
"DemoTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
"DemoTest",
"UnitTest1",
"TestMethod2",
new string[2]
{
"System.Int32",
"System.Int32",
},
"System.Void"),
new Msg::TestFileLocationProperty(@"D:\gth\RSCG_Examples\v2\rscg_examples\MSTest\src\DemoTest\UnitTest1.cs", new(new(15, -1), new(21, -1))),
},
GetArguments = static () => new MSTF::InternalUnsafeTestArgumentsEntry<(int left, int right)>[]
{
new MSTF::InternalUnsafeTestArgumentsEntry<(int left, int right)>((1, 2), "left: 1, right: 2"),
new MSTF::InternalUnsafeTestArgumentsEntry<(int left, int right)>((100, -97), "left: 100, right: -97"),
},
Body = static (testExecutionContext, data) =>
{
var instance = new UnitTest1();
try
{
instance.TestMethod2(data.Arguments.left, data.Arguments.right);
}
catch (global::System.Exception ex)
{
testExecutionContext.ReportException(ex, null);
}
},
},
},
};
}
}
namespace Microsoft.Testing.Framework.SourceGeneration
{
public static class SourceGeneratedTestingPlatformBuilderHook
{
public static void AddExtensions(Microsoft.Testing.Platform.Builder.ITestApplicationBuilder testApplicationBuilder, string[] _)
{
testApplicationBuilder.AddTestFramework(new Microsoft.Testing.Framework.Configurations.TestFrameworkConfiguration(System.Environment.ProcessorCount),
new DemoTest.SourceGeneratedTestNodesBuilder());
}
}
}
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by Microsoft Testing Framework Generator.
// </auto-generated>
//------------------------------------------------------------------------------
namespace DemoTest
{
using DemoTest;
using ColGen = global::System.Collections.Generic;
using CA = global::System.Diagnostics.CodeAnalysis;
using Sys = global::System;
using Tasks = global::System.Threading.Tasks;
using Msg = global::Microsoft.Testing.Platform.Extensions.Messages;
using MSTF = global::Microsoft.Testing.Framework;
using Cap = global::Microsoft.Testing.Platform.Capabilities.TestFramework;
using TrxReport = global::Microsoft.Testing.Extensions.TrxReport.Abstractions;
[CA::ExcludeFromCodeCoverage]
public sealed class SourceGeneratedTestNodesBuilder : MSTF::ITestNodesBuilder
{
private sealed class ClassCapabilities : TrxReport::ITrxReportCapability
{
bool TrxReport::ITrxReportCapability.IsSupported { get; } = true;
void TrxReport::ITrxReportCapability.Enable() {}
}
public ColGen::IReadOnlyCollection<Cap::ITestFrameworkCapability> Capabilities { get; } = new Cap::ITestFrameworkCapability[1] { new ClassCapabilities() };
public Tasks::Task<MSTF::TestNode[]> BuildAsync(MSTF::ITestSessionContext testSessionContext)
{
ColGen::List<MSTF::TestNode> namespace1Tests = new();
namespace1Tests.Add(DemoTest_UnitTest1.TestNode);
MSTF::TestNode root = new MSTF::TestNode
{
StableUid = "DemoTest",
DisplayName = "DemoTest",
Properties = Sys::Array.Empty<Msg::IProperty>(),
Tests = new MSTF::TestNode[]
{
new MSTF::TestNode
{
StableUid = "DemoTest.DemoTest",
DisplayName = "DemoTest",
Properties = Sys::Array.Empty<Msg::IProperty>(),
Tests = namespace1Tests.ToArray(),
},
},
};
return Tasks::Task.FromResult(new MSTF::TestNode[1] { root });
}
}
}
Code and pdf at
https://ignatandrei.github.io/RSCG_Examples/v2/docs/MSTest