diff --git a/Documentation/Troubleshooting.md b/Documentation/Troubleshooting.md index f9e66b032..3d8d00d09 100644 --- a/Documentation/Troubleshooting.md +++ b/Documentation/Troubleshooting.md @@ -244,4 +244,9 @@ You can live attach and debug collectors with `COVERLET_DATACOLLECTOR_OUTOFPROC_ set COVERLET_DATACOLLECTOR_OUTOFPROC_DEBUG=1 set COVERLET_DATACOLLECTOR_INPROC_DEBUG=1 ``` -You will be asked to attach a debugger through UI popup. +You will be asked to attach a debugger through UI popup. +To enable exceptions log for in-process data collectors +``` + set COVERLET_DATACOLLECTOR_INPROC_EXCEPTIONLOG_ENABLED=1 +``` + diff --git a/Documentation/VSTestIntegration.md b/Documentation/VSTestIntegration.md index 47fa12f0d..5471a00db 100644 --- a/Documentation/VSTestIntegration.md +++ b/Documentation/VSTestIntegration.md @@ -1,6 +1,14 @@ # Coverlet integration with VSTest (a.k.a. Visual Studio Test Platform) -**At the moment collectors integration supports only .NET Core applications and not .NET Framework ones.** +**Supported runtime versions:** +Before version `3.0.0` +- .NET Core >= 2.0 +- .NET Framework not fully supported(only out of process collector, could suffer of [known issue](https://github.com/coverlet-coverage/coverlet/blob/master/Documentation/KnownIssues.md#1-vstest-stops-process-execution-earlydotnet-test)) + +Since version `3.0.0` +- .NET Core >= 2.0 +- .NET Framework >= 4.6.1 + As explained in quick start section to use collectors you need to run *SDK v2.2.401* or newer and your project file must reference `coverlet.collector.dll` and a minimum version of `Microsoft.NET.Test.Sdk`. A sample project file looks like: diff --git a/src/coverlet.collector/DataCollection/CoverletSettingsParser.cs b/src/coverlet.collector/DataCollection/CoverletSettingsParser.cs index a3b1b1124..31509474a 100644 --- a/src/coverlet.collector/DataCollection/CoverletSettingsParser.cs +++ b/src/coverlet.collector/DataCollection/CoverletSettingsParser.cs @@ -237,7 +237,7 @@ private string[] ParseDoesNotReturnAttributes(XmlElement configurationElement) /// An array of the values in the element private string[] SplitElement(XmlElement element) { - return element?.InnerText?.Split(',', StringSplitOptions.RemoveEmptyEntries).Where(value => !string.IsNullOrWhiteSpace(value)).Select(value => value.Trim()).ToArray(); + return element?.InnerText?.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Where(value => !string.IsNullOrWhiteSpace(value)).Select(value => value.Trim()).ToArray(); } } } diff --git a/src/coverlet.collector/InProcDataCollection/CoverletInProcDataCollector.cs b/src/coverlet.collector/InProcDataCollection/CoverletInProcDataCollector.cs index 8c4dd05ef..5539d6b04 100644 --- a/src/coverlet.collector/InProcDataCollection/CoverletInProcDataCollector.cs +++ b/src/coverlet.collector/InProcDataCollection/CoverletInProcDataCollector.cs @@ -1,6 +1,7 @@ using System; using System.Diagnostics; using System.Reflection; +using System.Text; using coverlet.collector.Resources; using Coverlet.Collector.Utilities; @@ -14,6 +15,7 @@ namespace Coverlet.Collector.DataCollection public class CoverletInProcDataCollector : InProcDataCollection { private TestPlatformEqtTrace _eqtTrace; + private bool _enableExceptionLog = false; private void AttachDebugger() { @@ -24,10 +26,18 @@ private void AttachDebugger() } } - public void Initialize(IDataCollectionSink dataCollectionSink) + private void EnableExceptionLog() { + if (int.TryParse(Environment.GetEnvironmentVariable("COVERLET_DATACOLLECTOR_INPROC_EXCEPTIONLOG_ENABLED"), out int result) && result == 1) + { + _enableExceptionLog = true; + } + } + public void Initialize(IDataCollectionSink dataCollectionSink) + { AttachDebugger(); + EnableExceptionLog(); _eqtTrace = new TestPlatformEqtTrace(); _eqtTrace.Verbose("Initialize CoverletInProcDataCollector"); @@ -61,9 +71,12 @@ public void TestSessionEnd(TestSessionEndArgs testSessionEndArgs) } catch (Exception ex) { - _eqtTrace.Error("{0}: Failed to unload module with error: {1}", CoverletConstants.InProcDataCollectorName, ex); - string errorMessage = string.Format(Resources.FailedToUnloadModule, CoverletConstants.InProcDataCollectorName); - throw new CoverletDataCollectorException(errorMessage, ex); + if (_enableExceptionLog) + { + _eqtTrace.Error("{0}: Failed to unload module with error: {1}", CoverletConstants.InProcDataCollectorName, ex); + string errorMessage = string.Format(Resources.FailedToUnloadModule, CoverletConstants.InProcDataCollectorName); + throw new CoverletDataCollectorException(errorMessage, ex); + } } } } @@ -89,7 +102,25 @@ private Type GetInstrumentationClass(Assembly assembly) } catch (Exception ex) { - _eqtTrace.Warning("{0}: Failed to get Instrumentation class with error: {1}", CoverletConstants.InProcDataCollectorName, ex); + if (_enableExceptionLog) + { + StringBuilder exceptionString = new StringBuilder(); + exceptionString.AppendFormat("{0}: Failed to get Instrumentation class for assembly '{1}' with error: {2}", + CoverletConstants.InProcDataCollectorName, assembly, ex); + exceptionString.AppendLine(); + + if (ex is ReflectionTypeLoadException rtle) + { + exceptionString.AppendLine("ReflectionTypeLoadException list:"); + foreach (Exception loaderEx in rtle.LoaderExceptions) + { + exceptionString.AppendLine(loaderEx.ToString()); + } + } + + _eqtTrace.Warning(exceptionString.ToString()); + } + return null; } } diff --git a/src/coverlet.collector/coverlet.collector.csproj b/src/coverlet.collector/coverlet.collector.csproj index d6a7695a8..ba206705c 100644 --- a/src/coverlet.collector/coverlet.collector.csproj +++ b/src/coverlet.collector/coverlet.collector.csproj @@ -1,6 +1,6 @@  - netcoreapp2.0 + netstandard2.0 coverlet.collector true true