From 6988e40fde31520f1cd97e8627a9a0270ec466d0 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Wed, 23 Sep 2020 10:02:50 -0700 Subject: [PATCH] Include XML test results in local test runs Closes #47974 --- .../Source/RunTests/AssemblyScheduler.cs | 22 +++++++++---------- src/Tools/Source/RunTests/ITestExecutor.cs | 6 ++--- src/Tools/Source/RunTests/Options.cs | 6 ++--- .../Source/RunTests/ProcessTestExecutor.cs | 10 +++++++-- src/Tools/Source/RunTests/Program.cs | 2 +- src/Tools/Source/RunTests/TestRunner.cs | 2 +- 6 files changed, 26 insertions(+), 22 deletions(-) diff --git a/src/Tools/Source/RunTests/AssemblyScheduler.cs b/src/Tools/Source/RunTests/AssemblyScheduler.cs index 35c7c4fdd8f..adbdba3ec46 100644 --- a/src/Tools/Source/RunTests/AssemblyScheduler.cs +++ b/src/Tools/Source/RunTests/AssemblyScheduler.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -10,7 +9,6 @@ using System.Reflection.Metadata; using System.Reflection.PortableExecutable; using System.Text; -using System.Threading.Tasks; namespace RunTests { @@ -33,12 +31,12 @@ internal struct AssemblyInfo ExtraArguments = extraArguments; } - internal AssemblyInfo(string assemblyPath, string targetFrameworkMoniker, string architecture, bool useHmtl) + internal AssemblyInfo(string assemblyPath, string targetFrameworkMoniker, string architecture, bool includeHtml) { AssemblyPath = assemblyPath; DisplayName = Path.GetFileName(assemblyPath); - var suffix = useHmtl ? "html" : "xml"; + var suffix = includeHtml ? "html" : "xml"; ResultsFileName = $"{DisplayName}_{targetFrameworkMoniker}_{architecture}.{suffix}"; ExtraArguments = string.Empty; } @@ -91,23 +89,23 @@ private sealed class AssemblyInfoBuilder private readonly StringBuilder _builder = new StringBuilder(); private readonly string _assemblyPath; private readonly int _methodLimit; - private readonly bool _useHtml; + private readonly bool _includeHtml; private readonly bool _hasEventListenerGuard; private int _currentId; private List _currentTypeInfoList = new List(); - private AssemblyInfoBuilder(string assemblyPath, int methodLimit, bool useHtml, bool hasEventListenerGuard) + private AssemblyInfoBuilder(string assemblyPath, int methodLimit, bool includeHtml, bool hasEventListenerGuard) { _assemblyPath = assemblyPath; - _useHtml = useHtml; + _includeHtml = includeHtml; _methodLimit = methodLimit; _hasEventListenerGuard = hasEventListenerGuard; } - internal static void Build(string assemblyPath, int methodLimit, bool useHtml, List typeInfoList, out List partitionList, out List assemblyInfoList) + internal static void Build(string assemblyPath, int methodLimit, bool includeHtml, List typeInfoList, out List partitionList, out List assemblyInfoList) { var hasEventListenerGuard = typeInfoList.Any(x => x.FullName == EventListenerGuardFullName); - var builder = new AssemblyInfoBuilder(assemblyPath, methodLimit, useHtml, hasEventListenerGuard); + var builder = new AssemblyInfoBuilder(assemblyPath, methodLimit, includeHtml, hasEventListenerGuard); builder.Build(typeInfoList); partitionList = builder._partitionList; assemblyInfoList = builder._assemblyInfoList; @@ -169,7 +167,7 @@ private void FinishPartition() { var assemblyName = Path.GetFileName(_assemblyPath); var displayName = $"{assemblyName}.{_currentId}"; - var suffix = _useHtml ? "html" : "xml"; + var suffix = _includeHtml ? "html" : "xml"; var resultsFileName = $"{assemblyName}.{_currentId}.{suffix}"; var assemblyInfo = new AssemblyInfo( _assemblyPath, @@ -206,7 +204,7 @@ public IEnumerable Schedule(string assemblyPath, bool force = fals var typeInfoList = GetTypeInfoList(assemblyPath); var assemblyInfoList = new List(); var partitionList = new List(); - AssemblyInfoBuilder.Build(assemblyPath, _methodLimit, _options.UseHtml, typeInfoList, out partitionList, out assemblyInfoList); + AssemblyInfoBuilder.Build(assemblyPath, _methodLimit, _options.IncludeHtml, typeInfoList, out partitionList, out assemblyInfoList); // If the scheduling didn't actually produce multiple partition then send back an unpartitioned // representation. @@ -233,7 +231,7 @@ public IEnumerable Schedule(string assemblyPath, bool force = fals public AssemblyInfo CreateAssemblyInfo(string assemblyPath) { - return new AssemblyInfo(assemblyPath, _options.TargetFrameworkMoniker, _options.Test64 ? "x64" : "x86", _options.UseHtml); + return new AssemblyInfo(assemblyPath, _options.TargetFrameworkMoniker, _options.Test64 ? "x64" : "x86", _options.IncludeHtml); } private static List GetTypeInfoList(string assemblyPath) diff --git a/src/Tools/Source/RunTests/ITestExecutor.cs b/src/Tools/Source/RunTests/ITestExecutor.cs index fd5e99afef7..da5838f7848 100644 --- a/src/Tools/Source/RunTests/ITestExecutor.cs +++ b/src/Tools/Source/RunTests/ITestExecutor.cs @@ -15,18 +15,18 @@ namespace RunTests internal string OutputDirectory { get; } internal string Trait { get; } internal string NoTrait { get; } - internal bool UseHtml { get; } + internal bool IncludeHtml { get; } internal bool Test64 { get; } internal bool TestVsi { get; } - internal TestExecutionOptions(string xunitPath, ProcDumpInfo? procDumpInfo, string outputDirectory, string trait, string noTrait, bool useHtml, bool test64, bool testVsi) + internal TestExecutionOptions(string xunitPath, ProcDumpInfo? procDumpInfo, string outputDirectory, string trait, string noTrait, bool includeHtml, bool test64, bool testVsi) { XunitPath = xunitPath; ProcDumpInfo = procDumpInfo; OutputDirectory = outputDirectory; Trait = trait; NoTrait = noTrait; - UseHtml = useHtml; + IncludeHtml = includeHtml; Test64 = test64; TestVsi = testVsi; } diff --git a/src/Tools/Source/RunTests/Options.cs b/src/Tools/Source/RunTests/Options.cs index 11b10e572f7..0442b45435b 100644 --- a/src/Tools/Source/RunTests/Options.cs +++ b/src/Tools/Source/RunTests/Options.cs @@ -23,7 +23,7 @@ internal class Options /// /// Use HTML output files. /// - public bool UseHtml { get; set; } + public bool IncludeHtml { get; set; } /// /// Use the 64 bit test runner. @@ -119,7 +119,7 @@ bool isOption(string argument, string optionName, out string value) return false; } - var opt = new Options { XunitPath = args[0], UseHtml = true, TestResultXmlOutputDirectory = Path.Combine(Directory.GetCurrentDirectory(), "TestResults") }; + var opt = new Options { XunitPath = args[0], IncludeHtml = true, TestResultXmlOutputDirectory = Path.Combine(Directory.GetCurrentDirectory(), "TestResults") }; var index = 1; var allGood = true; while (index < args.Length) @@ -137,7 +137,7 @@ bool isOption(string argument, string optionName, out string value) } else if (comparer.Equals(current, "-xml")) { - opt.UseHtml = false; + opt.IncludeHtml = false; index++; } else if (isOption(current, "-tfm", out string targetFrameworkMoniker)) diff --git a/src/Tools/Source/RunTests/ProcessTestExecutor.cs b/src/Tools/Source/RunTests/ProcessTestExecutor.cs index bc42d74fe8a..cfe35995f65 100644 --- a/src/Tools/Source/RunTests/ProcessTestExecutor.cs +++ b/src/Tools/Source/RunTests/ProcessTestExecutor.cs @@ -32,11 +32,17 @@ public string GetCommandLineArguments(AssemblyInfo assemblyInfo) { var assemblyName = Path.GetFileName(assemblyInfo.AssemblyPath); var resultsFilePath = GetResultsFilePath(assemblyInfo); + var xmlResultsFilePath = Path.ChangeExtension(resultsFilePath, ".xml"); + var htmlResultsFilePath = Path.ChangeExtension(resultsFilePath, ".html"); var builder = new StringBuilder(); builder.AppendFormat(@"""{0}""", assemblyInfo.AssemblyPath); builder.AppendFormat(@" {0}", assemblyInfo.ExtraArguments); - builder.AppendFormat(@" -{0} ""{1}""", Options.UseHtml ? "html" : "xml", resultsFilePath); + builder.AppendFormat($@" -xml ""{xmlResultsFilePath}"""); + + if (Options.IncludeHtml) + builder.AppendFormat($@" -html ""{htmlResultsFilePath}"""); + builder.Append(" -noshadow -verbose"); if (!string.IsNullOrWhiteSpace(Options.Trait)) @@ -70,7 +76,7 @@ public async Task RunTestAsync(AssemblyInfo assemblyInfo, Cancellati var result = await RunTestAsyncInternal(assemblyInfo, retry: false, cancellationToken); // For integration tests (TestVsi), we make one more attempt to re-run failed tests. - if (Options.TestVsi && !Options.UseHtml && !result.Succeeded) + if (Options.TestVsi && !Options.IncludeHtml && !result.Succeeded) { return await RunTestAsyncInternal(assemblyInfo, retry: true, cancellationToken); } diff --git a/src/Tools/Source/RunTests/Program.cs b/src/Tools/Source/RunTests/Program.cs index f1cafabc698..a96a6c7289f 100644 --- a/src/Tools/Source/RunTests/Program.cs +++ b/src/Tools/Source/RunTests/Program.cs @@ -328,7 +328,7 @@ private static ProcessTestExecutor CreateTestExecutor(Options options) outputDirectory: options.TestResultXmlOutputDirectory, trait: options.Trait, noTrait: options.NoTrait, - useHtml: options.UseHtml, + includeHtml: options.IncludeHtml, test64: options.Test64, testVsi: options.TestVsi); return new ProcessTestExecutor(testExecutionOptions); diff --git a/src/Tools/Source/RunTests/TestRunner.cs b/src/Tools/Source/RunTests/TestRunner.cs index 4f1ef1a0579..1fce3fa637a 100644 --- a/src/Tools/Source/RunTests/TestRunner.cs +++ b/src/Tools/Source/RunTests/TestRunner.cs @@ -175,7 +175,7 @@ private void PrintFailedTestResult(TestResult testResult) } // If the results are html, use Process.Start to open in the browser. - if (_options.UseHtml && !string.IsNullOrEmpty(testResult.ResultsFilePath)) + if (_options.IncludeHtml && !string.IsNullOrEmpty(testResult.ResultsFilePath)) { Process.Start(testResult.ResultsFilePath); } -- GitLab