Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Do Not Review - Changes required for 15.8 timeline] Parent test result support for data driven tests #342

Closed
Closed
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
9 changes: 9 additions & 0 deletions src/Adapter/MSTest.CoreAdapter/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ internal static class Constants

internal static readonly TestProperty DoNotParallelizeProperty = TestProperty.Register("MSTestDiscoverer.DoNotParallelize", DoNotParallelizeLabel, typeof(bool), TestPropertyAttributes.Hidden, typeof(TestCase));

internal static readonly TestProperty ExecutionIdProperty = TestProperty.Register("ExecutionId", ExecutionIdLabel, typeof(Guid), TestPropertyAttributes.Hidden, typeof(TestResult));

internal static readonly TestProperty ParentExecIdProperty = TestProperty.Register("ParentExecId", ParentExecIdLabel, typeof(Guid), TestPropertyAttributes.Hidden, typeof(TestResult));

internal static readonly TestProperty InnerResultsCountProperty = TestProperty.Register("InnerResultsCount", InnerResultsCountLabel, typeof(int), TestPropertyAttributes.Hidden, typeof(TestResult));

#endregion

#region Private Constants
Expand All @@ -59,6 +65,9 @@ internal static class Constants
private const string PriorityLabel = "Priority";
private const string DeploymentItemsLabel = "DeploymentItems";
private const string DoNotParallelizeLabel = "DoNotParallelize";
private const string ExecutionIdLabel = "ExecutionId";
private const string ParentExecIdLabel = "ParentExecId";
private const string InnerResultsCountLabel = "InnerResultsCount";

#endregion
}
Expand Down
61 changes: 39 additions & 22 deletions src/Adapter/MSTest.CoreAdapter/Execution/TestMethodRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,15 @@ internal UnitTestResult[] RunTestMethod()
}
else
{
var parentResultWatch = new Stopwatch();
parentResultWatch.Start();
var parentResult = new UTF.TestResult
{
Outcome = UTF.UnitTestOutcome.InProgress,
ExecutionId = Guid.NewGuid()
};
results.Add(parentResult);

try
{
int rowIndex = 0;
Expand All @@ -260,12 +269,17 @@ internal UnitTestResult[] RunTestMethod()
new UTF.TestResult() { TestFailureException = new Exception(string.Format(CultureInfo.CurrentCulture, Resource.UTA_ExecuteThrewException, ex.Message), ex) }
};
}

watch.Stop();
foreach (var testResult in testResults)
{
testResult.DatarowIndex = rowIndex;
testResult.ExecutionId = Guid.NewGuid();
testResult.ParentExecId = parentResult.ExecutionId;
testResult.Duration = watch.Elapsed;

parentResult.Outcome = UnitTestOutcomeExtensions.GetMoreImportantOutcome(parentResult.Outcome, testResult.Outcome);
parentResult.InnerResultsCount++;
}

rowIndex++;
Expand All @@ -278,6 +292,10 @@ internal UnitTestResult[] RunTestMethod()
this.testContext.SetDataConnection(null);
this.testContext.SetDataRow(null);
}

parentResult.Outcome = UnitTestOutcomeExtensions.GetMoreImportantOutcome(parentResult.Outcome, UTF.UnitTestOutcome.Passed);
parentResultWatch.Stop();
parentResult.Duration = parentResultWatch.Elapsed;
}
}
catch (Exception ex)
Expand All @@ -287,7 +305,7 @@ internal UnitTestResult[] RunTestMethod()
failedResult.Outcome = UTF.UnitTestOutcome.Error;
failedResult.TestFailureException = ex;
failedResult.Duration = watch.Elapsed;
results.Add(failedResult);
results = new List<UTF.TestResult>() { failedResult };
}
}
else
Expand All @@ -296,6 +314,15 @@ internal UnitTestResult[] RunTestMethod()

if (testDataSources != null && testDataSources.Length > 0)
{
var parentResultWatch = new Stopwatch();
parentResultWatch.Start();
var parentResult = new UTF.TestResult
{
Outcome = UTF.UnitTestOutcome.InProgress,
ExecutionId = Guid.NewGuid()
};
results.Add(parentResult);

foreach (var testDataSource in testDataSources)
{
foreach (var data in testDataSource.GetData(this.testMethodInfo.MethodInfo))
Expand All @@ -317,12 +344,20 @@ internal UnitTestResult[] RunTestMethod()
foreach (var testResult in testResults)
{
testResult.DisplayName = testDataSource.GetDisplayName(this.testMethodInfo.MethodInfo, data);
testResult.ParentExecId = parentResult.ExecutionId;
parentResult.Outcome = UnitTestOutcomeExtensions.GetMoreImportantOutcome(parentResult.Outcome, testResult.Outcome);
parentResult.InnerResultsCount++;
}

results.AddRange(testResults);

this.testMethodInfo.SetArguments(null);
}
}

parentResult.Outcome = UnitTestOutcomeExtensions.GetMoreImportantOutcome(parentResult.Outcome, UTF.UnitTestOutcome.Passed);
parentResultWatch.Stop();
parentResult.Duration = parentResultWatch.Elapsed;
}
else
{
Expand All @@ -347,25 +382,7 @@ internal UnitTestResult[] RunTestMethod()

if (results != null && results.Count > 0)
{
// aggregate for data driven tests
UTF.UnitTestOutcome aggregateOutcome = UTF.UnitTestOutcome.Passed;

foreach (var result in results)
{
if (result.Outcome != UTF.UnitTestOutcome.Passed)
{
if (aggregateOutcome != UTF.UnitTestOutcome.Failed)
{
if (result.Outcome == UTF.UnitTestOutcome.Failed
|| aggregateOutcome != UTF.UnitTestOutcome.Timeout)
{
aggregateOutcome = result.Outcome;
}
}
}
}

this.testContext.SetOutcome(aggregateOutcome);
this.testContext.SetOutcome(results.First().Outcome);
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ public static UnitTestResult[] ToUnitTestResults(this UTF.TestResult[] testResul
unitTestResult.DisplayName = testResults[i].DisplayName;
unitTestResult.DatarowIndex = testResults[i].DatarowIndex;
unitTestResult.ResultFiles = testResults[i].ResultFiles;
unitTestResult.ExecutionId = testResults[i].ExecutionId;
unitTestResult.ParentExecId = testResults[i].ParentExecId;
unitTestResult.InnerResultsCount = testResults[i].InnerResultsCount;
unitTestResults[i] = unitTestResult;
}

Expand Down
19 changes: 19 additions & 0 deletions src/Adapter/MSTest.CoreAdapter/ObjectModel/UnitTestResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,21 @@ internal UnitTestResult(UnitTestOutcome outcome, string errorMessage)
/// </summary>
public string ErrorStackTrace { get; internal set; }

/// <summary>
/// Gets the execution id of the result
/// </summary>
public Guid ExecutionId { get; internal set; }

/// <summary>
/// Gets the parent execution id of the result
/// </summary>
public Guid ParentExecId { get; internal set; }

/// <summary>
/// Gets the inner results count of the result
/// </summary>
public int InnerResultsCount { get; internal set; }

/// <summary>
/// Gets the duration of the result
/// </summary>
Expand Down Expand Up @@ -149,6 +164,10 @@ internal TestResult ToTestResult(TestCase testCase, DateTimeOffset startTime, Da
EndTime = endTime
};

testResult.SetPropertyValue<Guid>(Constants.ExecutionIdProperty, this.ExecutionId);
testResult.SetPropertyValue<Guid>(Constants.ParentExecIdProperty, this.ParentExecId);
testResult.SetPropertyValue<int>(Constants.InnerResultsCountProperty, this.InnerResultsCount);

if (!string.IsNullOrEmpty(this.StandardOut))
{
TestResultMessage message = new TestResultMessage(TestResultMessage.StandardOutCategory, this.StandardOut);
Expand Down
15 changes: 15 additions & 0 deletions src/TestFramework/MSTest.Core/Attributes/VSTestAttributes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,21 @@ public TestResult()
/// </summary>
public string TestContextMessages { get; set; }

/// <summary>
/// Gets or sets the execution id of the result.
/// </summary>
public Guid ExecutionId { get; set; }

/// <summary>
/// Gets or sets the parent execution id of the result.
/// </summary>
public Guid ParentExecId { get; set; }

/// <summary>
/// Gets or sets the inner results count of the result.
/// </summary>
public int InnerResultsCount { get; set; }

/// <summary>
/// Gets or sets the duration of test execution.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -543,9 +543,31 @@ public void RunTestMethodShouldSetDataRowIndexForDataDrivenTestsWhenDataIsProvid
var results = testMethodRunner.RunTestMethod();

// check for datarowIndex
Assert.AreEqual(results[0].DatarowIndex, 0);
Assert.AreEqual(results[1].DatarowIndex, 1);
Assert.AreEqual(results[2].DatarowIndex, 2);
Assert.AreEqual(results[0].DatarowIndex, -1);
Assert.AreEqual(results[1].DatarowIndex, 0);
Assert.AreEqual(results[2].DatarowIndex, 1);
Assert.AreEqual(results[3].DatarowIndex, 2);
}

[TestMethodV1]
public void RunTestMethodShouldReturnParentResultForDataDrivenTests()
{
var testMethodInfo = new TestableTestmethodInfo(this.methodInfo, this.testClassInfo, this.testMethodOptions, () => new UTF.TestResult());
var testMethodRunner = new TestMethodRunner(testMethodInfo, this.testMethod, this.testContextImplementation, false);

UTF.DataSourceAttribute dataSourceAttribute = new UTF.DataSourceAttribute("DummyConnectionString", "DummyTableName");

var attribs = new Attribute[] { dataSourceAttribute };

// Setup mocks
this.testablePlatformServiceProvider.MockReflectionOperations.Setup(rf => rf.GetCustomAttributes(this.methodInfo, It.IsAny<Type>(), It.IsAny<bool>())).Returns(attribs);
this.testablePlatformServiceProvider.MockTestDataSource.Setup(tds => tds.GetData(testMethodInfo, this.testContextImplementation)).Returns(new object[] { 1, 2, 3 });

var results = testMethodRunner.RunTestMethod();

// check for parent result
Assert.AreEqual(4, results.Length);
Assert.AreEqual(results[0].ExecutionId, results[1].ParentExecId);
}

[TestMethodV1]
Expand All @@ -570,9 +592,10 @@ public void RunTestMethodShoudlRunOnlyDataSourceTestsWhenBothDataSourceAndDataRo
var results = testMethodRunner.RunTestMethod();

// check for datarowIndex as only DataSource Tests are Run
Assert.AreEqual(results[0].DatarowIndex, 0);
Assert.AreEqual(results[1].DatarowIndex, 1);
Assert.AreEqual(results[2].DatarowIndex, 2);
Assert.AreEqual(results[0].DatarowIndex, -1);
Assert.AreEqual(results[1].DatarowIndex, 0);
Assert.AreEqual(results[2].DatarowIndex, 1);
Assert.AreEqual(results[3].DatarowIndex, 2);
}

[TestMethodV1]
Expand All @@ -595,7 +618,7 @@ public void RunTestMethodShouldFillInDisplayNameWithDataRowDisplayNameIfProvided
this.testablePlatformServiceProvider.MockReflectionOperations.Setup(ro => ro.GetCustomAttributes(this.methodInfo, It.IsAny<Type>(), It.IsAny<bool>())).Returns(attribs);

var results = testMethodRunner.RunTestMethod();
Assert.AreEqual(results[0].DisplayName, "DataRowTestDisplayName");
Assert.AreEqual(results[1].DisplayName, "DataRowTestDisplayName");
}

[TestMethodV1]
Expand All @@ -617,7 +640,7 @@ public void RunTestMethodShouldFillInDisplayNameWithDataRowArgumentsIfNoDisplayN
this.testablePlatformServiceProvider.MockReflectionOperations.Setup(rf => rf.GetCustomAttributes(this.methodInfo, It.IsAny<Type>(), It.IsAny<bool>())).Returns(attribs);

var results = testMethodRunner.RunTestMethod();
Assert.AreEqual(results[0].DisplayName, "DummyTestMethod (2,DummyString)");
Assert.AreEqual(results[1].DisplayName, "DummyTestMethod (2,DummyString)");
}

[TestMethodV1]
Expand All @@ -640,8 +663,8 @@ public void RunTestMethodShouldSetResultFilesIfPresentForDataDrivenTests()
this.testablePlatformServiceProvider.MockReflectionOperations.Setup(rf => rf.GetCustomAttributes(this.methodInfo, It.IsAny<Type>(), It.IsAny<bool>())).Returns(attribs);

var results = testMethodRunner.RunTestMethod();
CollectionAssert.Contains(results[0].ResultFiles.ToList(), "C:\\temp.txt");
CollectionAssert.Contains(results[1].ResultFiles.ToList(), "C:\\temp.txt");
CollectionAssert.Contains(results[2].ResultFiles.ToList(), "C:\\temp.txt");
}

#region Test data
Expand Down