diff --git a/src/Adapter/MSTest.TestAdapter/Execution/TestMethodRunner.cs b/src/Adapter/MSTest.TestAdapter/Execution/TestMethodRunner.cs index a3ee59fa98..562bb7376e 100644 --- a/src/Adapter/MSTest.TestAdapter/Execution/TestMethodRunner.cs +++ b/src/Adapter/MSTest.TestAdapter/Execution/TestMethodRunner.cs @@ -161,43 +161,54 @@ internal UnitTestResult[] RunTestMethod() DebugEx.Assert(_testMethodInfo.TestMethod != null, "Test method should not be null."); List results = []; - bool isDataDriven = false; - var parentStopwatch = Stopwatch.StartNew(); - - if (_testMethodInfo.TestMethodOptions.Executor != null) + if (_testMethodInfo.TestMethodOptions.Executor == null) { - if (_test.DataType == DynamicDataType.ITestDataSource) - { - object?[]? data = DataSerializationHelper.Deserialize(_test.SerializedData); - TestResult[] testResults = ExecuteTestWithDataSource(null, data); - results.AddRange(testResults); - } - else if (ExecuteDataSourceBasedTests(results)) - { - isDataDriven = true; - } - else + PlatformServiceProvider.Instance.AdapterTraceLogger.LogError( + "Not able to get executor for method {0}.{1}", + _testMethodInfo.TestClassName, + _testMethodInfo.TestMethodName); + + TestResult emptyResult = new() { - _testContext.SetDisplayName(_test.DisplayName); - TestResult[] testResults = ExecuteTest(_testMethodInfo); + Outcome = UTF.UnitTestOutcome.Unknown, + TestFailureException = new TestFailedException(UnitTestOutcome.Error, Resource.UTA_NoTestResult), + }; + _testContext.SetOutcome(emptyResult.Outcome); - foreach (TestResult testResult in testResults) - { - if (StringEx.IsNullOrWhiteSpace(testResult.DisplayName)) - { - testResult.DisplayName = _test.DisplayName; - } - } + results.Add(emptyResult); + return results.ToUnitTestResults(); + } - results.AddRange(testResults); - } + bool isDataDriven = false; + var parentStopwatch = Stopwatch.StartNew(); + if (_test.DataType == DynamicDataType.ITestDataSource) + { + object?[]? data = DataSerializationHelper.Deserialize(_test.SerializedData); + TestResult[] testResults = ExecuteTestWithDataSource(null, data); + results.AddRange(testResults); + } + else if (TryExecuteDataSourceBasedTests(results)) + { + isDataDriven = true; + } + else if (TryExecuteFoldedDataDrivenTests(results)) + { + isDataDriven = true; } else { - PlatformServiceProvider.Instance.AdapterTraceLogger.LogError( - "Not able to get executor for method {0}.{1}", - _testMethodInfo.TestClassName, - _testMethodInfo.TestMethodName); + _testContext.SetDisplayName(_test.DisplayName); + TestResult[] testResults = ExecuteTest(_testMethodInfo); + + foreach (TestResult testResult in testResults) + { + if (StringEx.IsNullOrWhiteSpace(testResult.DisplayName)) + { + testResult.DisplayName = _test.DisplayName; + } + } + + results.AddRange(testResults); } // Get aggregate outcome. @@ -210,6 +221,7 @@ internal UnitTestResult[] RunTestMethod() // In legacy scenario #pragma warning disable CS0618 // Type or member is obsolete if (_test.TestIdGenerationStrategy == TestIdGenerationStrategy.Legacy) +#pragma warning restore CS0618 // Type or member is obsolete { parentStopwatch.Stop(); var parentResult = new TestResult @@ -221,7 +233,6 @@ internal UnitTestResult[] RunTestMethod() results = UpdateResultsWithParentInfo(results, parentResult); } -#pragma warning restore CS0618 // Type or member is obsolete else { results = UpdateResultsWithParentInfo(results); @@ -243,108 +254,112 @@ internal UnitTestResult[] RunTestMethod() return results.ToUnitTestResults(); } - private bool ExecuteDataSourceBasedTests(List results) + private bool TryExecuteDataSourceBasedTests(List results) { - bool isDataDriven = false; - DataSourceAttribute[] dataSourceAttribute = _testMethodInfo.GetAttributes(false); if (dataSourceAttribute is { Length: 1 }) { - isDataDriven = true; - Stopwatch watch = new(); - watch.Start(); + ExecuteTestFromDataSourceAttribute(results); + return true; + } - try + return false; + } + + private bool TryExecuteFoldedDataDrivenTests(List results) + { + IEnumerable? testDataSources = _testMethodInfo.GetAttributes(false)?.OfType(); + if (testDataSources?.Any() != true) + { + return false; + } + + foreach (UTF.ITestDataSource testDataSource in testDataSources) + { + IEnumerable? dataSource; + + // This code is to execute tests. To discover the tests code is in AssemblyEnumerator.ProcessTestDataSourceTests. + // Any change made here should be reflected in AssemblyEnumerator.ProcessTestDataSourceTests as well. + dataSource = testDataSource.GetData(_testMethodInfo.MethodInfo); + + if (!dataSource.Any()) { - IEnumerable? dataRows = PlatformServiceProvider.Instance.TestDataSource.GetData(_testMethodInfo, _testContext); + if (!MSTestSettings.CurrentSettings.ConsiderEmptyDataSourceAsInconclusive) + { + throw testDataSource.GetExceptionForEmptyDataSource(_testMethodInfo.MethodInfo); + } + + var inconclusiveResult = new TestResult + { + Outcome = UTF.UnitTestOutcome.Inconclusive, + }; + results.Add(inconclusiveResult); + continue; + } - if (dataRows == null) + foreach (object?[] data in dataSource) + { + try { - var inconclusiveResult = new TestResult - { - Outcome = UTF.UnitTestOutcome.Inconclusive, - Duration = watch.Elapsed, - }; - results.Add(inconclusiveResult); + TestResult[] testResults = ExecuteTestWithDataSource(testDataSource, data); + + results.AddRange(testResults); } - else + finally { - try - { - int rowIndex = 0; - - foreach (object dataRow in dataRows) - { - TestResult[] testResults = ExecuteTestWithDataRow(dataRow, rowIndex++); - results.AddRange(testResults); - } - } - finally - { - _testContext.SetDataConnection(null); - _testContext.SetDataRow(null); - } + _testMethodInfo.SetArguments(null); } } - catch (Exception ex) + } + + return true; + } + + private void ExecuteTestFromDataSourceAttribute(List results) + { + Stopwatch watch = new(); + watch.Start(); + + try + { + IEnumerable? dataRows = PlatformServiceProvider.Instance.TestDataSource.GetData(_testMethodInfo, _testContext); + if (dataRows == null) { - var failedResult = new TestResult + var inconclusiveResult = new TestResult { - Outcome = UTF.UnitTestOutcome.Error, - TestFailureException = ex, + Outcome = UTF.UnitTestOutcome.Inconclusive, Duration = watch.Elapsed, }; - results.Add(failedResult); + results.Add(inconclusiveResult); + return; } - } - else - { - IEnumerable? testDataSources = _testMethodInfo.GetAttributes(false)?.OfType(); - if (testDataSources != null) + try { - foreach (UTF.ITestDataSource testDataSource in testDataSources) + int rowIndex = 0; + + foreach (object dataRow in dataRows) { - isDataDriven = true; - IEnumerable? dataSource; - - // This code is to execute tests. To discover the tests code is in AssemblyEnumerator.ProcessTestDataSourceTests. - // Any change made here should be reflected in AssemblyEnumerator.ProcessTestDataSourceTests as well. - dataSource = testDataSource.GetData(_testMethodInfo.MethodInfo); - - if (!dataSource.Any()) - { - if (!MSTestSettings.CurrentSettings.ConsiderEmptyDataSourceAsInconclusive) - { - throw testDataSource.GetExceptionForEmptyDataSource(_testMethodInfo.MethodInfo); - } - - var inconclusiveResult = new TestResult - { - Outcome = UTF.UnitTestOutcome.Inconclusive, - }; - results.Add(inconclusiveResult); - continue; - } - - foreach (object?[] data in dataSource) - { - try - { - TestResult[] testResults = ExecuteTestWithDataSource(testDataSource, data); - - results.AddRange(testResults); - } - finally - { - _testMethodInfo.SetArguments(null); - } - } + TestResult[] testResults = ExecuteTestWithDataRow(dataRow, rowIndex++); + results.AddRange(testResults); } } + finally + { + _testContext.SetDataConnection(null); + _testContext.SetDataRow(null); + } + } + catch (Exception ex) + { + var failedResult = new TestResult + { + Outcome = UTF.UnitTestOutcome.Error, + TestFailureException = ex, + Duration = watch.Elapsed, + }; + results.Add(failedResult); } - - return isDataDriven; } private TestResult[] ExecuteTestWithDataSource(UTF.ITestDataSource? testDataSource, object?[]? data)