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
1 change: 1 addition & 0 deletions TestFx.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@
<Project Path="test/UnitTests/Microsoft.Testing.Extensions.UnitTests/Microsoft.Testing.Extensions.UnitTests.csproj" />
<Project Path="test/UnitTests/Microsoft.Testing.Extensions.VSTestBridge.UnitTests/Microsoft.Testing.Extensions.VSTestBridge.UnitTests.csproj" />
<Project Path="test/UnitTests/Microsoft.Testing.Platform.DotnetTestProtocolContract.UnitTests/Microsoft.Testing.Platform.DotnetTestProtocolContract.UnitTests.csproj" />
<Project Path="test/UnitTests/Microsoft.Testing.Platform.TerminalReporterContract.UnitTests/Microsoft.Testing.Platform.TerminalReporterContract.UnitTests.csproj" />
<Project Path="test/UnitTests/Microsoft.Testing.Platform.MSBuild.UnitTests/Microsoft.Testing.Platform.MSBuild.UnitTests.csproj" />
<Project Path="test/UnitTests/Microsoft.Testing.Platform.UnitTests/Microsoft.Testing.Platform.UnitTests.csproj" />
<Project Path="test/UnitTests/MSTest.Analyzers.UnitTests/MSTest.Analyzers.UnitTests.csproj" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using Microsoft.CodeAnalysis;
using Microsoft.Testing.Platform.Resources;

namespace Microsoft.Testing.Platform.Helpers;

[Embedded]
internal static class ApplicationStateGuard
{
// These are internal invariant-violation diagnostics for "impossible" states; they are intentionally NOT
// localized (matching e.g. System.Diagnostics.UnreachableException) so that this foundational helper has no
// dependency on PlatformResources and can be shared as source (e.g. with dotnet/sdk's terminal reporter).
private const string UnexpectedStateErrorMessage = "Unexpected state in file '{0}' at line '{1}'";
private const string UnreachableLocationErrorMessage = "This program location is thought to be unreachable. File='{0}' Line={1}";

public static void Ensure([DoesNotReturnIf(false)] bool condition, string errorMessage)
{
if (!condition)
Expand All @@ -23,14 +28,14 @@ public static void Ensure([DoesNotReturnIf(false)] bool condition, [CallerFilePa
{
throw new InvalidOperationException(string.Format(
CultureInfo.InvariantCulture,
PlatformResources.UnexpectedStateErrorMessage,
UnexpectedStateErrorMessage,
path, line));
}
}

public static InvalidOperationException Unreachable([CallerFilePath] string? path = null, [CallerLineNumber] int line = 0)
=> new(string.Format(
CultureInfo.InvariantCulture,
PlatformResources.UnreachableLocationErrorMessage,
UnreachableLocationErrorMessage,
path, line));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<Project>

<!--
Shared-source manifest for the Microsoft.Testing.Platform *terminal UI reporter*.

PURPOSE
The terminal reporter (progress rendering, summary, ANSI/non-ANSI terminals, state model) is hard-forked
into dotnet/sdk's 'dotnet test' implementation. This .props lets the same source files be compiled into
another assembly - a standalone consumer test, or (once packaged as a source NuGet) the dotnet/sdk copy -
so the reporter has a single source of truth instead of being duplicated by hand.

SCOPE
The set is the reporter + its rendering/state types + the small platform abstractions it depends on
(IConsole/IStopwatch/IColor/System* + RoslynString/ApplicationStateGuard/StackTraceHelper/TargetFrameworkParser
/TestRunSummaryHelper). It deliberately EXCLUDES TerminalTestReporterCommandLineOptionsProvider.cs (MTP
command-line specific - the SDK has its own CLI) and TerminalResources.cs (the hand-written [Embedded]
accessor used by in-repo IVT-linked consumers; standalone consumers compile the resx instead - see below).

The reporter + rendering + state types are [Microsoft.CodeAnalysis.Embedded], so a consumer that also
references Microsoft.Testing.Platform never sees them as conflicting types. The small platform abstractions
in this set (IConsole/IStopwatch/IColor/SystemConsole/SystemConsoleColor/SystemStopwatch) are NOT embedded -
they are foundational, platform-wide types used far beyond the terminal. A consumer that compiles this
contract AND references Microsoft.Testing.Platform will therefore get benign CS0436 conflict warnings for
those types (the compiler uses the locally-compiled copy); such consumers should suppress CS0436 (the
in-repo standalone test does). A consumer that does NOT reference Microsoft.Testing.Platform - the real
target, e.g. dotnet/sdk's 'dotnet test' - sees no conflict at all.

USAGE
Import this file from any project that needs the reporter source. Microsoft.Testing.Platform itself does
NOT import it (it compiles these files via its default source globbing); importing it there would
double-include them.

- Source consumers (e.g. the standalone contract test project) get the .cs as <Compile> items and the resx
as an <EmbeddedResource GenerateSource="true"> (the defaults below), so the generated TerminalResources
accessor + satellites are embedded in the consumer's own assembly. No IS_CORE_MTP symbol is needed:
TerminalResources.cs (the only IS_CORE_MTP-conditional file) is excluded, and the resx generates the
accessor unconditionally.
- A future Microsoft.Testing.Platform.DotnetTestTerminal package sets TerminalReporterContractCompile=false
and instead packs @(TerminalReporterContractSource) + @(TerminalReporterContractResource) as contentFiles,
so the NuGet and the source-share never drift.
-->

<PropertyGroup>
<_TerminalContractPlatform>$(MSBuildThisFileDirectory)..\..</_TerminalContractPlatform>
</PropertyGroup>

<!-- The canonical list of shared reporter source (.cs). -->
<ItemGroup>
<!-- Reporter + rendering + state (terminal folder), minus the MTP-CLI options provider and the hand-written resx accessor. -->
<TerminalReporterContractSource Include="$(MSBuildThisFileDirectory)*.cs"
Exclude="$(MSBuildThisFileDirectory)TerminalTestReporterCommandLineOptionsProvider.cs;$(MSBuildThisFileDirectory)TerminalResources.cs" />

<!-- Small platform abstractions the reporter depends on. -->
<TerminalReporterContractSource Include="$(_TerminalContractPlatform)\Helpers\RoslynString.cs" />
<TerminalReporterContractSource Include="$(_TerminalContractPlatform)\Helpers\ApplicationStateGuard.cs" />
<TerminalReporterContractSource Include="$(_TerminalContractPlatform)\Helpers\StackTraceHelper.cs" />
<TerminalReporterContractSource Include="$(_TerminalContractPlatform)\Helpers\System\IConsole.cs" />
<TerminalReporterContractSource Include="$(_TerminalContractPlatform)\Helpers\System\IStopwatch.cs" />
<TerminalReporterContractSource Include="$(_TerminalContractPlatform)\Helpers\System\SystemConsole.cs" />
<TerminalReporterContractSource Include="$(_TerminalContractPlatform)\Helpers\System\SystemStopwatch.cs" />
<TerminalReporterContractSource Include="$(_TerminalContractPlatform)\OutputDevice\IColor.cs" />
<TerminalReporterContractSource Include="$(_TerminalContractPlatform)\OutputDevice\SystemConsoleColor.cs" />
<TerminalReporterContractSource Include="$(_TerminalContractPlatform)\OutputDevice\TargetFrameworkParser.cs" />
<TerminalReporterContractSource Include="$(_TerminalContractPlatform)\OutputDevice\TestRunSummaryHelper.cs" />
</ItemGroup>

<!-- The shared localized resource (resx + xlf) the reporter strings come from. -->
<ItemGroup>
<TerminalReporterContractResource Include="$(MSBuildThisFileDirectory)TerminalResources.resx" />
</ItemGroup>

<ItemGroup Condition=" '$(TerminalReporterContractCompile)' != 'false' ">
<Compile Include="@(TerminalReporterContractSource)" Link="TerminalReporter\%(RecursiveDir)%(Filename)%(Extension)" />
<!-- No Link on the resource: its manifest name / generated-accessor namespace must stay
Microsoft.Testing.Platform.OutputDevice.Terminal.TerminalResources so the reporter source resolves it. -->
<EmbeddedResource Include="@(TerminalReporterContractResource)" GenerateSource="true" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#if !IS_CORE_MTP
Expand All @@ -15,11 +15,8 @@

namespace Microsoft.Testing.Platform.OutputDevice.Terminal;

// Strongly-typed accessor for TerminalResources.resx. In core MTP the accessor is generated by Arcade
// (GenerateSource). We add this [Embedded] partial so the type is embedded per-assembly when the terminal
// reporter source is shared with external consumers (e.g. dotnet/sdk's 'dotnet test'). When linked into an
// assembly that does NOT compile the resx (e.g. the unit-test project), the !IS_CORE_MTP block provides a
// ResourceManager pointing at the core MTP assembly, mirroring the PlatformResources pattern.
// Strongly-typed accessor for TerminalResources.resx; [Embedded] so it is per-assembly when shared. The
// !IS_CORE_MTP branch points the ResourceManager at the core MTP assembly for in-repo linked consumers.
[Embedded]
internal static partial class TerminalResources
{
Expand All @@ -32,83 +29,91 @@ internal static partial class TerminalResources

internal static string @Aborted => GetResourceString("Aborted");

internal static string @ActiveTestsRunning_FullTestsCount => GetResourceString("ActiveTestsRunning_FullTestsCount");

internal static string @ActiveTestsRunning_MoreTestsCount => GetResourceString("ActiveTestsRunning_MoreTestsCount");

internal static string @Actual => GetResourceString("Actual");

internal static string @CancelledLowercase => GetResourceString("CancelledLowercase");

internal static string @CancellingTestSession => GetResourceString("CancellingTestSession");

internal static string @PressCtrlCAgainToForceExit => GetResourceString("PressCtrlCAgainToForceExit");
internal static string @ConsoleIsAlreadyInBatchingMode => GetResourceString("ConsoleIsAlreadyInBatchingMode");

internal static string @DurationLowercase => GetResourceString("DurationLowercase");

internal static string @Expected => GetResourceString("Expected");

internal static string @Failed => GetResourceString("Failed");

internal static string @FailedLowercase => GetResourceString("FailedLowercase");

internal static string @ForTest => GetResourceString("ForTest");

internal static string @InProcessArtifactsProduced => GetResourceString("InProcessArtifactsProduced");

internal static string @OutOfProcessArtifactsProduced => GetResourceString("OutOfProcessArtifactsProduced");
internal static string @MinimumExpectedTestsPolicyViolation => GetResourceString("MinimumExpectedTestsPolicyViolation");

internal static string @PassedLowercase => GetResourceString("PassedLowercase");

internal static string @SkippedLowercase => GetResourceString("SkippedLowercase");
internal static string @OutOfProcessArtifactsProduced => GetResourceString("OutOfProcessArtifactsProduced");

internal static string @TotalLowercase => GetResourceString("TotalLowercase");
internal static string @Passed => GetResourceString("Passed");

internal static string @ConsoleIsAlreadyInBatchingMode => GetResourceString("ConsoleIsAlreadyInBatchingMode");
internal static string @PassedLowercase => GetResourceString("PassedLowercase");

internal static string @DurationLowercase => GetResourceString("DurationLowercase");
internal static string @PressCtrlCAgainToForceExit => GetResourceString("PressCtrlCAgainToForceExit");

internal static string @TestRunSummary => GetResourceString("TestRunSummary");
internal static string @SkippedLowercase => GetResourceString("SkippedLowercase");

internal static string @StackFrameAt => GetResourceString("StackFrameAt");

internal static string @StackFrameIn => GetResourceString("StackFrameIn");

internal static string @TerminalNoAnsiOptionDescription => GetResourceString("TerminalNoAnsiOptionDescription");
internal static string @StandardError => GetResourceString("StandardError");

internal static string @StandardOutput => GetResourceString("StandardOutput");

internal static string @SucceededLowercase => GetResourceString("SucceededLowercase");

internal static string @TerminalAnsiOptionDescription => GetResourceString("TerminalAnsiOptionDescription");

internal static string @TerminalAnsiOptionInvalidArgument => GetResourceString("TerminalAnsiOptionInvalidArgument");

internal static string @TerminalNoAnsiOptionDescription => GetResourceString("TerminalNoAnsiOptionDescription");

internal static string @TerminalNoProgressOptionDescription => GetResourceString("TerminalNoProgressOptionDescription");

internal static string @TerminalProgressOptionDescription => GetResourceString("TerminalProgressOptionDescription");
internal static string @TerminalOutputOptionDescription => GetResourceString("TerminalOutputOptionDescription");

internal static string @TerminalProgressOptionInvalidArgument => GetResourceString("TerminalProgressOptionInvalidArgument");
internal static string @TerminalOutputOptionInvalidArgument => GetResourceString("TerminalOutputOptionInvalidArgument");

internal static string @TerminalProgressHeartbeat => GetResourceString("TerminalProgressHeartbeat");

internal static string @TerminalProgressHeartbeatActiveSuffix => GetResourceString("TerminalProgressHeartbeatActiveSuffix");

internal static string @TerminalProgressSlowTest => GetResourceString("TerminalProgressSlowTest");

internal static string @TerminalTestReporterDescription => GetResourceString("TerminalTestReporterDescription");

internal static string @TerminalTestReporterDisplayName => GetResourceString("TerminalTestReporterDisplayName");
internal static string @TerminalProgressOptionDescription => GetResourceString("TerminalProgressOptionDescription");

internal static string @TerminalOutputOptionDescription => GetResourceString("TerminalOutputOptionDescription");
internal static string @TerminalProgressOptionInvalidArgument => GetResourceString("TerminalProgressOptionInvalidArgument");

internal static string @TerminalOutputOptionInvalidArgument => GetResourceString("TerminalOutputOptionInvalidArgument");
internal static string @TerminalProgressSlowTest => GetResourceString("TerminalProgressSlowTest");

internal static string @TerminalShowStdoutOptionDescription => GetResourceString("TerminalShowStdoutOptionDescription");
internal static string @TerminalShowOutputOptionInvalidArgument => GetResourceString("TerminalShowOutputOptionInvalidArgument");

internal static string @TerminalShowStderrOptionDescription => GetResourceString("TerminalShowStderrOptionDescription");

internal static string @TerminalShowOutputOptionInvalidArgument => GetResourceString("TerminalShowOutputOptionInvalidArgument");
internal static string @TerminalShowStdoutOptionDescription => GetResourceString("TerminalShowStdoutOptionDescription");

internal static string @StandardError => GetResourceString("StandardError");
internal static string @TerminalTestReporterDescription => GetResourceString("TerminalTestReporterDescription");

internal static string @StandardOutput => GetResourceString("StandardOutput");
internal static string @TerminalTestReporterDisplayName => GetResourceString("TerminalTestReporterDisplayName");

internal static string @TestDiscoverySummarySingular => GetResourceString("TestDiscoverySummarySingular");

internal static string @ActiveTestsRunning_MoreTestsCount => GetResourceString("ActiveTestsRunning_MoreTestsCount");
internal static string @TestRunSummary => GetResourceString("TestRunSummary");

internal static string @ActiveTestsRunning_FullTestsCount => GetResourceString("ActiveTestsRunning_FullTestsCount");
internal static string @TotalLowercase => GetResourceString("TotalLowercase");

internal static string @SucceededLowercase => GetResourceString("SucceededLowercase");
internal static string @ZeroTestsRan => GetResourceString("ZeroTestsRan");

#endif
}
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@
<data name="Expected" xml:space="preserve">
<value>Expected</value>
</data>
<data name="Failed" xml:space="preserve">
<value>Failed</value>
</data>
<data name="FailedLowercase" xml:space="preserve">
<value>failed</value>
</data>
Expand All @@ -146,9 +149,16 @@
<data name="InProcessArtifactsProduced" xml:space="preserve">
<value>In process file artifacts produced:</value>
</data>
<data name="MinimumExpectedTestsPolicyViolation" xml:space="preserve">
<value>Minimum expected tests policy violation, tests ran {0}, minimum expected {1}</value>
<comment>{0} is the number of tests that ran. {1} is the minimum expected number of tests.</comment>
</data>
<data name="OutOfProcessArtifactsProduced" xml:space="preserve">
<value>Out of process file artifacts produced:</value>
</data>
<data name="Passed" xml:space="preserve">
<value>Passed</value>
</data>
<data name="PassedLowercase" xml:space="preserve">
<value>passed</value>
</data>
Expand All @@ -158,6 +168,9 @@
<data name="TotalLowercase" xml:space="preserve">
<value>total</value>
</data>
<data name="ZeroTestsRan" xml:space="preserve">
<value>Zero tests ran</value>
</data>
<data name="ConsoleIsAlreadyInBatchingMode" xml:space="preserve">
<value>Console is already in batching mode.</value>
<comment>Exception that is thrown when console is already collecting input into a batch (into a string builder), and code asks to enable batching mode again.</comment>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@
<target state="translated">Očekáváno</target>
<note />
</trans-unit>
<trans-unit id="Failed">
<source>Failed</source>
<target state="translated">Neúspěšné</target>
<note />
</trans-unit>
<trans-unit id="FailedLowercase">
<source>failed</source>
<target state="translated">selhalo</target>
Expand All @@ -52,6 +57,11 @@
<target state="translated">Vytvořené artefakty souboru v procesu:</target>
<note />
</trans-unit>
<trans-unit id="MinimumExpectedTestsPolicyViolation">
<source>Minimum expected tests policy violation, tests ran {0}, minimum expected {1}</source>
<target state="translated">Minimální očekávané porušení zásad testů, spuštěné testy: {0}, očekávané minimum: {1}</target>
<note>{0} is the number of tests that ran. {1} is the minimum expected number of tests.</note>
</trans-unit>
<trans-unit id="ActiveTestsRunning_MoreTestsCount">
<source>and {0} more</source>
<target state="translated">a ještě {0}</target>
Expand All @@ -67,6 +77,11 @@
<target state="translated">Vytvořené artefakty souboru mimo proces:</target>
<note />
</trans-unit>
<trans-unit id="Passed">
<source>Passed</source>
<target state="translated">Úspěšné</target>
<note />
</trans-unit>
<trans-unit id="PassedLowercase">
<source>passed</source>
<target state="translated">úspěch</target>
Expand Down Expand Up @@ -215,6 +230,11 @@ Platné hodnoty jsou All, Failed, None. Výchozí hodnota je All (nebo Failed, k
<target state="translated">Souhrn testovacího běhu:</target>
<note />
</trans-unit>
<trans-unit id="ZeroTestsRan">
<source>Zero tests ran</source>
<target state="translated">Spustila se nula testů</target>
<note />
</trans-unit>
<trans-unit id="TotalLowercase">
<source>total</source>
<target state="translated">celkem</target>
Expand Down
Loading
Loading