Skip to content

Commit

Permalink
TW-89577 use test result DisplayName in reporting if `TEAMCITY_USE_…
Browse files Browse the repository at this point in the history
…TEST_RESULT_DISPLAY_NAME` env var set to `true`
  • Loading branch information
mchechulnikov committed Oct 1, 2024
1 parent 99b9f51 commit 8adb752
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 10 deletions.
55 changes: 48 additions & 7 deletions TeamCity.VSTest.TestLogger.Tests/MessageHandlerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ public class MessageHandlerTests
private readonly List<string> _lines = [];
private readonly MessageHandler _events;
private readonly Mock<ISuiteNameProvider> _suiteNameProvider;
private readonly Mock<ITestNameProvider> _testNameProvider;
private readonly Mock<IIdGenerator> _idGenerator;
private readonly Mock<IAttachments> _attachments;
private readonly Mock<IOptions> _options;

public MessageHandlerTests()
{
Expand All @@ -31,15 +33,15 @@ public MessageHandlerTests()

_idGenerator = new Mock<IIdGenerator>();
_attachments = new Mock<IAttachments>();

var testNameProvider = new Mock<ITestNameProvider>();
testNameProvider.Setup(i => i.GetTestName(It.IsAny<string>(), It.IsAny<string>())).Returns<string, string>((fullyQualifiedName, _) => fullyQualifiedName);
_options = new Mock<IOptions>();
_testNameProvider = new Mock<ITestNameProvider>();
_testNameProvider.Setup(i => i.GetTestName(It.IsAny<string>(), It.IsAny<string>())).Returns<string, string>((fullyQualifiedName, _) => fullyQualifiedName);

var eventRegistry = new Mock<IEventRegistry>();
var failedTestsWriter = new Mock<IFailedTestsReportWriter>();

var root = new Root(_lines);
_events = new MessageHandler(root, _suiteNameProvider.Object, _attachments.Object, testNameProvider.Object, eventRegistry.Object, failedTestsWriter.Object);
_events = new MessageHandler(root, _suiteNameProvider.Object, _attachments.Object, _testNameProvider.Object, eventRegistry.Object, failedTestsWriter.Object, _options.Object);
}

private static TestResultEventArgs CreateTestResult(
Expand All @@ -48,19 +50,25 @@ private static TestResultEventArgs CreateTestResult(
string source = "assembly.dll",
string? errorMessage = default,
string? errorStackTrace = default,
string extensionId = TeamCityTestLogger.ExtensionId)
string extensionId = TeamCityTestLogger.ExtensionId,
string resultDisplayName = "test1 result display name",
string caseDisplayName = "test1 case display name")
{
return new TestResultEventArgs(
new TestResult(
new TestCase(
fullyQualifiedName,
new Uri(extensionId),
source))
source)
{
DisplayName = caseDisplayName
})
{
Outcome = outcome,
Duration = TimeSpan.FromSeconds(1),
ErrorMessage = errorMessage,
ErrorStackTrace = errorStackTrace
ErrorStackTrace = errorStackTrace,
DisplayName = resultDisplayName
});
}

Expand Down Expand Up @@ -314,4 +322,37 @@ public void ShouldPublishAttachedFiles()
// Then
_attachments.Verify(i => i.SendAttachment("assembly.dll: test1", attachment, It.IsAny<ITeamCityTestWriter>() ));
}

[Theory]
[InlineData(true, "test1 result display name")]
[InlineData(false, "test1 case display name")]
public void ShouldUseTestResultDisplayNameWhenOptionEnabled(bool useTestResultDisplayName, string expectedDisplayName)
{
// Given
_options.Setup(o => o.UseTestResultDisplayName).Returns(useTestResultDisplayName);

// When
_events.OnTestResult(CreateTestResult());
_events.OnTestRunComplete();

// Then
_testNameProvider.Verify(p => p.GetTestName(It.IsAny<string>(), expectedDisplayName), Times.Once);
}

[Theory]
[InlineData("")]
[InlineData(" ")]
public void ShouldUseTestCaseDisplayNameWhenOptionEnabledButResultDisplayNameIsEmpty(string emptyResultDisplayName)
{
// Given
const string caseDisplayName = "case display name";
_options.Setup(o => o.UseTestResultDisplayName).Returns(true);

// When
_events.OnTestResult(CreateTestResult(resultDisplayName: emptyResultDisplayName, caseDisplayName: caseDisplayName));
_events.OnTestRunComplete();

// Then
_testNameProvider.Verify(p => p.GetTestName(It.IsAny<string>(), caseDisplayName), Times.Once);
}
}
5 changes: 5 additions & 0 deletions TeamCity.VSTest.TestLogger.Tests/TestNameProviderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ public class TestNameProviderTests
[InlineData("", "Abc", "Abc")]
[InlineData(" ", "Abc", "Abc")]
[InlineData(null, null, "")]
[InlineData(
"TeamCityTestCount.Tests.DynamicDataClassTest",
"DynamicDataClassTest (TeamCityTestCount.Tests+TestClass,2)",
"TeamCityTestCount.Tests.DynamicDataClassTest(TeamCityTestCount.Tests+TestClass,2)"
)]
public void ShouldProvideName(string? fullyQualifiedName, string? displayName, string expected)
{
// Given
Expand Down
2 changes: 2 additions & 0 deletions TeamCity.VSTest.TestLogger/IOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,6 @@ internal interface IOptions
bool MetadataEnable { get; }

TeamCityVersion TestMetadataSupportVersion { get; }

public bool UseTestResultDisplayName { get; }
}
14 changes: 12 additions & 2 deletions TeamCity.VSTest.TestLogger/MessageHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ internal class MessageHandler : IMessageHandler
private readonly ITestNameProvider _testNameProvider;
private readonly IEventRegistry _eventRegistry;
private readonly IFailedTestsReportWriter _failedTestsReportWriter;
private readonly IOptions _options;
private ITeamCityWriter? _flowWriter;
private ITeamCityWriter? _blockWriter;

Expand All @@ -24,14 +25,16 @@ internal MessageHandler(
IAttachments attachments,
ITestNameProvider testNameProvider,
IEventRegistry eventRegistry,
IFailedTestsReportWriter failedTestsReportWriter)
IFailedTestsReportWriter failedTestsReportWriter,
IOptions options)
{
_rootWriter = rootWriter ?? throw new ArgumentNullException(nameof(rootWriter));
_suiteNameProvider = suiteNameProvider ?? throw new ArgumentNullException(nameof(suiteNameProvider));
_attachments = attachments ?? throw new ArgumentNullException(nameof(attachments));
_testNameProvider = testNameProvider ?? throw new ArgumentNullException(nameof(testNameProvider));
_eventRegistry = eventRegistry ?? throw new ArgumentNullException(nameof(eventRegistry));
_failedTestsReportWriter = failedTestsReportWriter ?? throw new ArgumentNullException(nameof(failedTestsReportWriter));
_options = options;
}

public void OnTestRunMessage(TestRunMessageEventArgs? ev)
Expand All @@ -47,8 +50,12 @@ public void OnTestResult(TestResultEventArgs? ev)

var result = ev.Result;
var testCase = result.TestCase;
// For data-driven tests which don't usually have a unique display name
// before execution is better to use display name from the test run result rather that from testCase.
// It makes a display name enriched with test parameters what makes test display name unique
var displayName = _options.UseTestResultDisplayName && !IsNullOrWhiteSpace(result.DisplayName) ? result.DisplayName : testCase.DisplayName;
var suiteName = _suiteNameProvider.GetSuiteName(testCase.Source);
var testName = _testNameProvider.GetTestName(testCase.FullyQualifiedName, testCase.DisplayName);
var testName = _testNameProvider.GetTestName(testCase.FullyQualifiedName, displayName);
if (string.IsNullOrEmpty(testName))
{
testName = testCase.Id.ToString();
Expand Down Expand Up @@ -134,4 +141,7 @@ public void OnTestRunComplete()
_rootWriter.Dispose();
_failedTestsReportWriter.Dispose();
}

private static bool IsNullOrWhiteSpace(string value) =>
string.IsNullOrEmpty(value) || value.Trim().Length == 0;
}
4 changes: 4 additions & 0 deletions TeamCity.VSTest.TestLogger/Options.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ internal class Options : IOptions
private static readonly string ServiceMessagesBackupPathVal;
private static readonly bool MetadataEnableVal;
private static readonly string FailedTestsReportSavePathVal;
private static readonly bool UseTestResultDisplayNameVal;

static Options()
{
Expand Down Expand Up @@ -56,6 +57,7 @@ static Options()
AllowExperimentalVal = GetBool(GetEnvironmentVariable("TEAMCITY_LOGGER_ALLOW_EXPERIMENTAL"), true);
MetadataEnableVal = GetBool(GetEnvironmentVariable("TEAMCITY_DOTNET_TEST_METADATA_ENABLE"), true);
FailedTestsReportSavePathVal = GetEnvironmentVariable("TEAMCITY_FAILED_TESTS_REPORTING_PATH");
UseTestResultDisplayNameVal = GetBool(GetEnvironmentVariable("TEAMCITY_USE_TEST_RESULT_DISPLAY_NAME"), false);

Environment.SetEnvironmentVariable("TEAMCITY_PROJECT_NAME", string.Empty);
}
Expand Down Expand Up @@ -84,6 +86,8 @@ static Options()

public TeamCityVersion TestMetadataSupportVersion => TestMetadataSupportVersionVal;

public bool UseTestResultDisplayName => UseTestResultDisplayNameVal;

private static string GetEnvironmentVariable(string name) => Envs.TryGetValue(name, out var val) ? val : string.Empty;

private static bool GetBool(string value, bool defaultValue) => !string.IsNullOrEmpty(value) && bool.TryParse(value, out var result) ? result : defaultValue;
Expand Down
3 changes: 2 additions & 1 deletion TeamCity.VSTest.TestLogger/ServiceLocatorNet35.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ public ServiceLocatorNet35()
new Attachments(this, idGenerator, teamCityWriter, testAttachmentPathResolver),
new TestNameProvider(),
eventContext,
new FailedTestsReportWriter(this, new BytesWriterFactory()));
new FailedTestsReportWriter(this, new BytesWriterFactory()),
this);
}

public IMessageWriter MessageWriter { get; }
Expand Down

0 comments on commit 8adb752

Please sign in to comment.