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

Updating debugging features and some code cleanup #926

Merged
merged 2 commits into from
Dec 11, 2021
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
368 changes: 360 additions & 8 deletions .editorconfig

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion build.cake
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ var configuration = Argument("configuration", "Release");
//////////////////////////////////////////////////////////////////////

var version = "4.2.0";
var modifier = "-alpha.919.3";
var modifier = "-alpha.4";

var dbgSuffix = configuration.ToLower() == "debug" ? "-dbg" : "";
var packageVersion = version + modifier + dbgSuffix;
Expand Down
14 changes: 13 additions & 1 deletion src/NUnitTestAdapter/AdapterSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ public interface IAdapterSettings
bool StopOnError { get; }
TestOutcome MapWarningTo { get; }
bool UseTestNameInConsoleOutput { get; }
bool FreakMode { get; }
DisplayNameOptions DisplayName { get; }
char FullnameSeparator { get; }
DiscoveryMethod DiscoveryMethod { get; }
Expand All @@ -120,6 +119,12 @@ public interface IAdapterSettings
void RestoreRandomSeed(string dirname);

bool EnsureAttachmentFileScheme { get; }

// For Internal Development use
bool FreakMode { get; } // displays metadata instead of real data in Test Explorer
bool Debug { get; }
bool DebugExecution { get; }
bool DebugDiscovery { get; }
}

public enum VsTestCategoryType
Expand Down Expand Up @@ -269,11 +274,15 @@ public AdapterSettings(ITestLogger logger)
public bool DumpVsInput { get; private set; }

public bool FreakMode { get; private set; }
public bool Debug { get; private set; }
public bool DebugExecution { get; private set; }
public bool DebugDiscovery { get; private set; }

#endregion




#endregion

#region Public Methods
Expand Down Expand Up @@ -393,6 +402,9 @@ private void ExtractNUnitDiagnosticSettings(XmlNode nunitNode)
FreakMode = GetInnerTextAsBool(nunitNode, nameof(FreakMode), false);
InternalTraceLevel = GetInnerTextWithLog(nunitNode, nameof(InternalTraceLevel), "Off", "Error", "Warning",
"Info", "Verbose", "Debug");
Debug = GetInnerTextAsBool(nunitNode, nameof(Debug), false);
DebugExecution = Debug || GetInnerTextAsBool(nunitNode, nameof(DebugExecution), false);
DebugDiscovery = Debug || GetInnerTextAsBool(nunitNode, nameof(DebugDiscovery), false);
}

private void UpdateTestProperties(XmlDocument doc)
Expand Down
8 changes: 4 additions & 4 deletions src/NUnitTestAdapter/CategoryList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,10 @@ private bool IsInternalProperty(NUnitProperty property)
}

// Property names starting with '_' are for internal use only, but over time this has changed, so we now use a list
if (!showInternalProperties &&
_internalProperties.Contains(property.Name))
return true;
return string.IsNullOrEmpty(property.Name) || property.Name[0] == '_' || string.IsNullOrEmpty(property.Value);
return (!showInternalProperties &&
_internalProperties.Contains(property.Name)) || (string.IsNullOrEmpty(property.Name) ||
property.Name[0] == '_' ||
string.IsNullOrEmpty(property.Value));
}

private void AddTraitsToCache(IDictionary<string, TraitsFeature.CachedTestCaseInfo> traitsCache, string key, NUnitProperty property)
Expand Down
7 changes: 1 addition & 6 deletions src/NUnitTestAdapter/Execution.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,7 @@ public interface IExecutionContext

public static class ExecutionFactory
{
public static Execution Create(IExecutionContext ctx)
{
if (ctx.Settings.DesignMode) // We come from IDE
return new IdeExecution(ctx);
return new VsTestExecution(ctx);
}
public static Execution Create(IExecutionContext ctx) => ctx.Settings.DesignMode ? new IdeExecution(ctx) : new VsTestExecution(ctx);
}

public abstract class Execution
Expand Down
2 changes: 1 addition & 1 deletion src/NUnitTestAdapter/Internal/TimingLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public TimingLogger ReStart()

public TimingLogger LogTime(string leadText = "")
{
if (settings.Verbosity < 5)
if (settings.Verbosity < 5 || Stopwatch == null)
return this;
var ts = Stopwatch.Elapsed;
string elapsedTime = $"{ts.Hours:00}:{ts.Minutes:00}:{ts.Seconds:00}.{ts.Milliseconds / 10:00}";
Expand Down
19 changes: 8 additions & 11 deletions src/NUnitTestAdapter/NUnit3TestDiscoverer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,11 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ***********************************************************************

// #define LAUNCHDEBUGGER

using System;
using System.Collections.Generic;
using System.ComponentModel;
#if LAUNCHDEBUGGER
using System.Diagnostics;
#endif
using System.IO;
using System.Linq;
using System.Xml;
Expand Down Expand Up @@ -57,11 +54,8 @@ public sealed class NUnit3TestDiscoverer : NUnitTestAdapter, ITestDiscoverer

public void DiscoverTests(IEnumerable<string> sources, IDiscoveryContext discoveryContext, IMessageLogger messageLogger, ITestCaseDiscoverySink discoverySink)
{
#if LAUNCHDEBUGGER
if (!Debugger.IsAttached)
Debugger.Launch();
#endif
Initialize(discoveryContext, messageLogger);
CheckIfDebug();
TestLog.Info($"NUnit Adapter {AdapterVersion}: Test discovery starting");

// Ensure any channels registered by other adapters are unregistered
Expand Down Expand Up @@ -182,10 +176,6 @@ private int ProcessTestCases(NUnitResults results, ITestCaseDiscoverySink discov
{
try
{
#if LAUNCHDEBUGGER
if (!Debugger.IsAttached)
Debugger.Launch();
#endif
var testCase = testConverterForXml.ConvertTestCase(new NUnitEventTestCase(testNode));
discoverySink.SendTestCase(testCase);
cases += 1;
Expand All @@ -199,6 +189,13 @@ private int ProcessTestCases(NUnitResults results, ITestCaseDiscoverySink discov
return cases;
}

private void CheckIfDebug()
{
if (!Settings.DebugDiscovery)
return;
if (!Debugger.IsAttached)
Debugger.Launch();
}
#endregion
}
}
76 changes: 45 additions & 31 deletions src/NUnitTestAdapter/NUnit3TestExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,17 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ***********************************************************************

// #define LAUNCHDEBUGGER

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;

using Microsoft.VisualStudio.TestPlatform.ObjectModel;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter;

using NUnit.Engine;
using NUnit.VisualStudio.TestAdapter.Dump;
using NUnit.VisualStudio.TestAdapter.Internal;
Expand All @@ -57,7 +58,8 @@ public enum RunType


[ExtensionUri(ExecutorUri)]
public sealed class NUnit3TestExecutor : NUnitTestAdapter, ITestExecutor, IDisposable, INUnit3TestExecutor, IExecutionContext
public sealed class NUnit3TestExecutor : NUnitTestAdapter, ITestExecutor, IDisposable, INUnit3TestExecutor,
IExecutionContext
{
#region Properties

Expand Down Expand Up @@ -96,17 +98,15 @@ public sealed class NUnit3TestExecutor : NUnitTestAdapter, ITestExecutor, IDispo
/// <param name="frameworkHandle">Test log to send results and messages through.</param>
public void RunTests(IEnumerable<string> sources, IRunContext runContext, IFrameworkHandle frameworkHandle)
{
#if LAUNCHDEBUGGER
if (!Debugger.IsAttached)
Debugger.Launch();
#endif
Initialize(runContext, frameworkHandle);
CheckIfDebug();
TestLog.Debug("RunTests by IEnumerable<string>");
InitializeForExecution(runContext, frameworkHandle);

if (Settings.InProcDataCollectorsAvailable && sources.Count() > 1)
{
TestLog.Error("Failed to run tests for multiple assemblies when InProcDataCollectors specified in run configuration.");
TestLog.Error(
"Failed to run tests for multiple assemblies when InProcDataCollectors specified in run configuration.");
Unload();
return;
}
Expand All @@ -119,18 +119,22 @@ public void RunTests(IEnumerable<string> sources, IRunContext runContext, IFrame
var vsTestFilter = VsTestFilterFactory.CreateVsTestFilter(Settings, runContext);
filter = builder.ConvertVsTestFilterToNUnitFilter(vsTestFilter);
}

filter ??= builder.FilterByWhere(Settings.Where);

foreach (string assemblyName in sources)
{
try
{
string assemblyPath = Path.IsPathRooted(assemblyName) ? assemblyName : Path.Combine(Directory.GetCurrentDirectory(), assemblyName);
string assemblyPath = Path.IsPathRooted(assemblyName)
? assemblyName
: Path.Combine(Directory.GetCurrentDirectory(), assemblyName);
RunAssembly(assemblyPath, null, filter);
}
catch (Exception ex)
{
if (ex is TargetInvocationException) { ex = ex.InnerException; }

TestLog.Warning("Exception thrown executing tests", ex);
}
}
Expand All @@ -156,11 +160,8 @@ private void SetRunTypeByStrings() =>
/// <param name="frameworkHandle">The FrameworkHandle.</param>
public void RunTests(IEnumerable<TestCase> tests, IRunContext runContext, IFrameworkHandle frameworkHandle)
{
#if LAUNCHDEBUGGER
if (!Debugger.IsAttached)
Debugger.Launch();
#endif
Initialize(runContext, frameworkHandle);
CheckIfDebug();
TestLog.Debug("RunTests by IEnumerable<TestCase>");
InitializeForExecution(runContext, frameworkHandle);
RunType = RunType.Ide;
Expand All @@ -170,7 +171,8 @@ public void RunTests(IEnumerable<TestCase> tests, IRunContext runContext, IFrame
var assemblyGroups = tests.GroupBy(tc => tc.Source);
if (IsInProcDataCollectorsSpecifiedWithMultipleAssemblies(assemblyGroups))
{
TestLog.Error("Failed to run tests for multiple assemblies when InProcDataCollectors specified in run configuration.");
TestLog.Error(
"Failed to run tests for multiple assemblies when InProcDataCollectors specified in run configuration.");
Unload();
return;
}
Expand All @@ -181,7 +183,9 @@ public void RunTests(IEnumerable<TestCase> tests, IRunContext runContext, IFrame
try
{
string assemblyName = assemblyGroup.Key;
string assemblyPath = Path.IsPathRooted(assemblyName) ? assemblyName : Path.Combine(Directory.GetCurrentDirectory(), assemblyName);
string assemblyPath = Path.IsPathRooted(assemblyName)
? assemblyName
: Path.Combine(Directory.GetCurrentDirectory(), assemblyName);

var filterBuilder = CreateTestFilterBuilder();
var filter = filterBuilder.FilterByList(assemblyGroup);
Expand All @@ -191,6 +195,7 @@ public void RunTests(IEnumerable<TestCase> tests, IRunContext runContext, IFrame
catch (Exception ex)
{
if (ex is TargetInvocationException) { ex = ex.InnerException; }

TestLog.Warning("Exception thrown executing tests", ex);
}

Expand All @@ -202,7 +207,8 @@ public void RunTests(IEnumerable<TestCase> tests, IRunContext runContext, IFrame
Unload();
}

private bool IsInProcDataCollectorsSpecifiedWithMultipleAssemblies(IEnumerable<IGrouping<string, TestCase>> assemblyGroups)
private bool IsInProcDataCollectorsSpecifiedWithMultipleAssemblies(
IEnumerable<IGrouping<string, TestCase>> assemblyGroups)
=> Settings.InProcDataCollectorsAvailable && assemblyGroups.Count() > 1;

void ITestExecutor.Cancel()
Expand Down Expand Up @@ -244,7 +250,9 @@ public void InitializeForExecution(IRunContext runContext, IFrameworkHandle fram

if (VsTestFilter.IsEmpty)
{
if (!(enableShutdown && !runContext.KeepAlive)) // Otherwise causes exception when run as commandline, illegal to enableshutdown when Keepalive is false, might be only VS2012
if (!(enableShutdown &&
!runContext
.KeepAlive)) // Otherwise causes exception when run as commandline, illegal to enableshutdown when Keepalive is false, might be only VS2012
frameworkHandle.EnableShutdownAfterTestRun = enableShutdown;
}

Expand All @@ -253,9 +261,7 @@ public void InitializeForExecution(IRunContext runContext, IFrameworkHandle fram

private void RunAssembly(string assemblyPath, IGrouping<string, TestCase> testCases, TestFilter filter)
{
string actionText = Debugger.IsAttached ? "Debugging " : "Running ";
string selectionText = filter == null || filter == TestFilter.Empty ? "all" : "selected";
TestLog.Info(actionText + selectionText + " tests in " + assemblyPath);
LogActionAndSelection(assemblyPath, filter);
RestoreRandomSeed(assemblyPath);
Dump = DumpXml.CreateDump(assemblyPath, testCases, Settings);

Expand All @@ -279,9 +285,7 @@ private void RunAssembly(string assemblyPath, IGrouping<string, TestCase> testCa
}
else
{
TestLog.Info(discoveryResults.HasNoNUnitTests
? " NUnit couldn't find any tests in " + assemblyPath
: " NUnit failed to load " + assemblyPath);
TestLog.InfoNoTests(discoveryResults.HasNoNUnitTests, assemblyPath);
}
}
catch (Exception ex) when (ex is BadImageFormatException || ex.InnerException is BadImageFormatException)
Expand All @@ -292,7 +296,8 @@ private void RunAssembly(string assemblyPath, IGrouping<string, TestCase> testCa
catch (FileNotFoundException ex)
{
// Probably from the GetExportedTypes in NUnit.core, attempting to find an assembly, not a problem if it is not NUnit here
TestLog.Warning(" Dependent Assembly " + ex.FileName + " of " + assemblyPath + " not found. Can be ignored if not an NUnit project.");
TestLog.Warning(" Dependent Assembly " + ex.FileName + " of " + assemblyPath +
" not found. Can be ignored if not an NUnit project.");
}
catch (Exception ex)
{
Expand All @@ -312,12 +317,18 @@ private void RunAssembly(string assemblyPath, IGrouping<string, TestCase> testCa
// can happen if CLR throws CannotUnloadAppDomainException, for example
// due to a long-lasting operation in a protected region (catch/finally clause).
if (ex is TargetInvocationException) { ex = ex.InnerException; }

TestLog.Warning($" Exception thrown unloading tests from {assemblyPath}", ex);
}
}
}


private void LogActionAndSelection(string assemblyPath, TestFilter filter)
{
string actionText = Debugger.IsAttached ? "Debugging " : "Running ";
string selectionText = filter == null || filter == TestFilter.Empty ? "all" : "selected";
TestLog.Info(actionText + selectionText + " tests in " + assemblyPath);
}


private void RestoreRandomSeed(string assemblyPath)
Expand All @@ -328,12 +339,7 @@ private void RestoreRandomSeed(string assemblyPath)
}


private NUnitTestFilterBuilder CreateTestFilterBuilder()
{
return new (NUnitEngineAdapter.GetService<ITestFilterService>(), Settings);
}


private NUnitTestFilterBuilder CreateTestFilterBuilder() => new (NUnitEngineAdapter.GetService<ITestFilterService>(), Settings);


private void CreateTestOutputFolder()
Expand Down Expand Up @@ -367,5 +373,13 @@ public void StopRun()
}

public IDumpXml Dump { get; private set; }

private void CheckIfDebug()
{
if (!Settings.DebugExecution)
return;
if (!Debugger.IsAttached)
Debugger.Launch();
}
}
}
}
Loading