diff --git a/src/Microsoft.TestPlatform.Common/Interfaces/Engine/ITestCaseEventsHandler.cs b/src/Microsoft.TestPlatform.Common/Interfaces/Engine/ITestCaseEventsHandler.cs
index 094a993463..4e27cc48bf 100644
--- a/src/Microsoft.TestPlatform.Common/Interfaces/Engine/ITestCaseEventsHandler.cs
+++ b/src/Microsoft.TestPlatform.Common/Interfaces/Engine/ITestCaseEventsHandler.cs
@@ -3,6 +3,7 @@
namespace Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine
{
+ using System.Collections.Generic;
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
///
@@ -33,7 +34,8 @@ public interface ITestCaseEventsHandler
/// Send session start event.
/// The purpose of this is to perform any initialization before the test case level events are sent.
///
- void SendSessionStart();
+ /// The session start properties.
+ void SendSessionStart(IDictionary properties);
///
/// Sends session end event.
diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/InProcDataCollectionExtensionManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/InProcDataCollectionExtensionManager.cs
index ec084cd18d..5c16f9eb3f 100644
--- a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/InProcDataCollectionExtensionManager.cs
+++ b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/InProcDataCollectionExtensionManager.cs
@@ -5,11 +5,11 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.DataCollection
{
using System;
using System.Collections.Generic;
+ using System.IO;
using System.Linq;
using System.Reflection;
-
+ using System.Xml;
using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.DataCollection.Interfaces;
- using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Execution;
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.DataCollection;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.DataCollector.InProcDataCollector;
@@ -25,6 +25,8 @@ internal class InProcDataCollectionExtensionManager
private IDataCollectionSink inProcDataCollectionSink;
+ private string defaultCodeBase;
+
///
/// Loaded in-proc datacollectors collection
///
@@ -39,10 +41,14 @@ internal class InProcDataCollectionExtensionManager
///
/// The data collection test case event manager.
///
- public InProcDataCollectionExtensionManager(string runSettings, ITestEventsPublisher testEventsPublisher)
+ ///
+ /// The default codebase to be used by inproc data collector
+ ///
+ public InProcDataCollectionExtensionManager(string runSettings, ITestEventsPublisher testEventsPublisher, string defaultCodeBase)
{
this.InProcDataCollectors = new Dictionary();
this.inProcDataCollectionSink = new InProcDataCollectionSink();
+ this.defaultCodeBase = defaultCodeBase;
// Initialize InProcDataCollectors
this.InitializeInProcDataCollectors(runSettings);
@@ -74,13 +80,13 @@ public InProcDataCollectionExtensionManager(string runSettings, ITestEventsPubli
///
/// The .
///
- protected virtual IInProcDataCollector CreateDataCollector(DataCollectorSettings dataCollectorSettings, TypeInfo interfaceTypeInfo)
+ protected virtual IInProcDataCollector CreateDataCollector(string assemblyQualifiedName, string codebase, XmlElement configuration, TypeInfo interfaceTypeInfo)
{
var inProcDataCollector = new InProcDataCollector(
- dataCollectorSettings.CodeBase,
- dataCollectorSettings.AssemblyQualifiedName,
+ codebase,
+ assemblyQualifiedName,
interfaceTypeInfo,
- dataCollectorSettings.Configuration.OuterXml);
+ configuration?.OuterXml);
inProcDataCollector.LoadDataCollector(this.inProcDataCollectionSink);
@@ -98,7 +104,7 @@ protected virtual IInProcDataCollector CreateDataCollector(DataCollectorSettings
///
private void TriggerTestSessionStart(object sender, SessionStartEventArgs e)
{
- TestSessionStartArgs testSessionStartArgs = new TestSessionStartArgs();
+ TestSessionStartArgs testSessionStartArgs = new TestSessionStartArgs(this.GetSessionStartProperties(e));
this.TriggerInProcDataCollectionMethods(Constants.TestSessionStartMethodName, testSessionStartArgs);
}
@@ -172,7 +178,7 @@ private void TriggerUpdateTestResult(object sender, TestResultEventArgs e)
private void InitializeInProcDataCollectors(string runSettings)
{
try
- {
+ {
// Check if runsettings contains in-proc datacollector element
var inProcDataCollectionRunSettings = XmlRunSettingsUtilities.GetInProcDataCollectionRunSettings(runSettings);
var inProcDataCollectionSettingsPresentInRunSettings = inProcDataCollectionRunSettings?.IsCollectionEnabled ?? false;
@@ -189,7 +195,10 @@ private void InitializeInProcDataCollectors(string runSettings)
var interfaceTypeInfo = typeof(InProcDataCollection).GetTypeInfo();
foreach (var inProcDc in this.inProcDataCollectorSettingsCollection)
{
- var inProcDataCollector = this.CreateDataCollector(inProcDc, interfaceTypeInfo);
+ var codeBase = this.GetCodebase(inProcDc.CodeBase);
+ var assemblyQualifiedName = inProcDc.AssemblyQualifiedName;
+ var configuration = inProcDc.Configuration;
+ var inProcDataCollector = this.CreateDataCollector(assemblyQualifiedName, codeBase, configuration, interfaceTypeInfo);
this.InProcDataCollectors[inProcDataCollector.AssemblyQualifiedName] = inProcDataCollector;
}
}
@@ -204,6 +213,24 @@ private void InitializeInProcDataCollectors(string runSettings)
}
}
+ ///
+ /// Gets codebase for inproc datacollector
+ /// Uses default codebase if given path is not absolute path of inproc datacollector
+ ///
+ /// The run Settings.
+ /// Codebase
+ private string GetCodebase(string codeBase)
+ {
+ return Path.IsPathRooted(codeBase) ? codeBase : Path.Combine(this.defaultCodeBase, codeBase);
+ }
+
+ private IDictionary GetSessionStartProperties(SessionStartEventArgs sessionStartEventArgs)
+ {
+ var properties = new Dictionary();
+ properties.Add(Constants.TestSourcesPropertyName, sessionStartEventArgs.GetPropertyValue>(Constants.TestSourcesPropertyName));
+ return properties;
+ }
+
private void TriggerInProcDataCollectionMethods(string methodName, InProcDataCollectionArgs methodArg)
{
try
@@ -263,5 +290,10 @@ internal static class Constants
/// The test case end method name.
///
public const string TestCaseEndMethodName = "TestCaseEnd";
+
+ ///
+ /// Test sources property name
+ ///
+ public const string TestSourcesPropertyName = "TestSources";
}
}
diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/EventHandlers/TestCaseEventsHandler.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/EventHandlers/TestCaseEventsHandler.cs
index 790803bb67..9faa970901 100644
--- a/src/Microsoft.TestPlatform.CrossPlatEngine/EventHandlers/TestCaseEventsHandler.cs
+++ b/src/Microsoft.TestPlatform.CrossPlatEngine/EventHandlers/TestCaseEventsHandler.cs
@@ -4,6 +4,7 @@
namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.EventHandlers
{
using System;
+ using System.Collections.Generic;
using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.DataCollection.Interfaces;
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.DataCollection;
@@ -51,9 +52,9 @@ public void SendTestResult(TestResult result)
}
///
- public void SendSessionStart()
+ public void SendSessionStart(IDictionary properties)
{
- this.SessionStart.SafeInvoke(this, new SessionStartEventArgs(), "TestCaseEventsHandler.RaiseSessionStart");
+ this.SessionStart.SafeInvoke(this, new SessionStartEventArgs(properties), "TestCaseEventsHandler.RaiseSessionStart");
}
///
diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/BaseRunTests.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/BaseRunTests.cs
index d2fb0b2579..6c1e761ada 100644
--- a/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/BaseRunTests.cs
+++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/BaseRunTests.cs
@@ -209,7 +209,7 @@ public void RunTests()
try
{
// Call Session-Start event on in-proc datacollectors
- this.testCaseEventsHandler?.SendSessionStart();
+ this.SendSessionStart();
elapsedTime = this.RunTestsInternal();
@@ -230,7 +230,7 @@ public void RunTests()
finally
{
// Trigger Session End on in-proc datacollectors
- this.testCaseEventsHandler?.SendSessionEnd();
+ this.SendSessionEnd();
try
{
@@ -288,6 +288,10 @@ internal void Cancel()
protected abstract void InvokeExecutor(LazyExtension executor, Tuple executorUriExtensionTuple, RunContext runContext, IFrameworkHandle frameworkHandle);
+ protected abstract void SendSessionStart();
+
+ protected abstract void SendSessionEnd();
+
#endregion
private void CancelTestRunInternal(ITestExecutor executor)
@@ -309,17 +313,6 @@ private void SetContext()
{
this.testRunCache = new TestRunCache(this.testExecutionContext.FrequencyOfRunStatsChangeEvent, this.testExecutionContext.RunStatsChangeEventTimeout, this.OnCacheHit);
- // Initialize data collectors if declared in run settings.
- if (DataCollectionTestCaseEventSender.Instance != null && XmlRunSettingsUtilities.IsDataCollectionEnabled(this.runSettings))
- {
- var outOfProcDataCollectionManager = new ProxyOutOfProcDataCollectionManager(DataCollectionTestCaseEventSender.Instance, this.testEventsPublisher);
- }
-
- if (XmlRunSettingsUtilities.IsInProcDataCollectionEnabled(this.runSettings))
- {
- var inProcDataCollectionExtensionManager = new InProcDataCollectionExtensionManager(this.runSettings, this.testEventsPublisher);
- }
-
this.runContext = new RunContext();
this.runContext.RunSettings = RunSettingsUtilities.CreateAndInitializeRunSettings(this.runSettings);
this.runContext.KeepAlive = this.testExecutionContext.KeepAlive;
diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/ExecutionManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/ExecutionManager.cs
index 815ae614cc..1a526ba435 100644
--- a/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/ExecutionManager.cs
+++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/ExecutionManager.cs
@@ -9,13 +9,18 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Execution
using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework;
using Microsoft.VisualStudio.TestPlatform.Common.SettingsProvider;
+ using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities;
using Microsoft.VisualStudio.TestPlatform.CoreUtilities.Tracing;
using Microsoft.VisualStudio.TestPlatform.CoreUtilities.Tracing.Interfaces;
+ using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.DataCollection;
+ using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.DataCollection.Interfaces;
+ using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Utilities;
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine.ClientProtocol;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine.TesthostProtocol;
+ using Microsoft.VisualStudio.TestPlatform.ObjectModel.Utilities;
///
/// Orchestrates test execution related functionality for the engine communicating with the test host process.
@@ -85,6 +90,8 @@ public void StartTestRun(
{
try
{
+ this.InitializeDataCollectors(runSettings, testCaseEventsHandler as ITestEventsPublisher, TestSourcesUtility.GetDefaultCodebasePath(adapterSourceMap));
+
this.activeTestRun = new RunTestsWithSources(this.requestData, adapterSourceMap, package, runSettings, testExecutionContext, testCaseEventsHandler, runEventsHandler);
this.activeTestRun.RunTests();
@@ -119,6 +126,8 @@ public void StartTestRun(
{
try
{
+ this.InitializeDataCollectors(runSettings, testCaseEventsHandler as ITestEventsPublisher, TestSourcesUtility.GetDefaultCodebasePath(tests));
+
this.activeTestRun = new RunTestsWithTests(this.requestData, tests, package, runSettings, testExecutionContext, testCaseEventsHandler, runEventsHandler);
this.activeTestRun.RunTests();
@@ -196,6 +205,24 @@ private void LoadExtensions()
}
}
+ ///
+ /// Initializes outproc and inproc data collectors.
+ ///
+ private void InitializeDataCollectors(string runSettings, ITestEventsPublisher testEventsPublisher, string defaultCodeBase)
+ {
+ // Initialize outproc data collectors if declared in run settings.
+ if (DataCollectionTestCaseEventSender.Instance != null && XmlRunSettingsUtilities.IsDataCollectionEnabled(runSettings))
+ {
+ var outOfProcDataCollectionManager = new ProxyOutOfProcDataCollectionManager(DataCollectionTestCaseEventSender.Instance, testEventsPublisher);
+ }
+
+ // Initialize inproc data collectors if declared in run settings.
+ if (XmlRunSettingsUtilities.IsInProcDataCollectionEnabled(runSettings))
+ {
+ var inProcDataCollectionExtensionManager = new InProcDataCollectionExtensionManager(runSettings, testEventsPublisher, defaultCodeBase);
+ }
+ }
+
#endregion
}
}
diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/RunTestsWithSources.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/RunTestsWithSources.cs
index 3d0308e087..aca4e83318 100644
--- a/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/RunTestsWithSources.cs
+++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/RunTestsWithSources.cs
@@ -15,6 +15,7 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Execution
using Microsoft.VisualStudio.TestPlatform.CoreUtilities.Tracing;
using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Adapter;
using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Discovery;
+ using Microsoft.VisualStudio.TestPlatform.ObjectModel;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine.ClientProtocol;
@@ -30,6 +31,8 @@ internal class RunTestsWithSources : BaseRunTests
private Dictionary, IEnumerable> executorUriVsSourceList;
+ private ITestCaseEventsHandler testCaseEventsHandler;
+
public RunTestsWithSources(IRequestData requestData, Dictionary> adapterSourceMap, string package, string runSettings, TestExecutionContext testExecutionContext, ITestCaseEventsHandler testCaseEventsHandler, ITestRunEventsHandler testRunEventsHandler)
: this(requestData, adapterSourceMap, package, runSettings, testExecutionContext, testCaseEventsHandler, testRunEventsHandler, null)
{
@@ -52,6 +55,7 @@ internal RunTestsWithSources(IRequestData requestData, Dictionary
+ /// Sends Session-End event on in-proc datacollectors
+ ///
+ protected override void SendSessionEnd()
+ {
+ this.testCaseEventsHandler?.SendSessionEnd();
+ }
+
+ ///
+ /// Sends Session-Start event on in-proc datacollectors
+ ///
+ protected override void SendSessionStart()
+ {
+ // Send session start with test sources in property bag for session start event args.
+ if (this.testCaseEventsHandler == null)
+ {
+ return;
+ }
+
+ var properties = new Dictionary();
+ properties.Add("TestSources", TestSourcesUtility.GetSources(this.adapterSourceMap));
+
+ this.testCaseEventsHandler.SendSessionStart(properties);
+ }
}
}
diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/RunTestsWithTests.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/RunTestsWithTests.cs
index b189f37fde..52f32507ce 100644
--- a/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/RunTestsWithTests.cs
+++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/RunTestsWithTests.cs
@@ -11,6 +11,7 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Execution
using Microsoft.VisualStudio.TestPlatform.Common.Interfaces;
using Microsoft.VisualStudio.TestPlatform.CoreUtilities.Tracing;
using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Adapter;
+ using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Utilities;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine.ClientProtocol;
@@ -24,6 +25,8 @@ internal class RunTestsWithTests : BaseRunTests
private Dictionary, List> executorUriVsTestList;
+ private ITestCaseEventsHandler testCaseEventsHandler;
+
public RunTestsWithTests(IRequestData requestData, IEnumerable testCases, string package, string runSettings, TestExecutionContext testExecutionContext, ITestCaseEventsHandler testCaseEventsHandler, ITestRunEventsHandler testRunEventsHandler)
: this(requestData, testCases, package, runSettings, testExecutionContext, testCaseEventsHandler, testRunEventsHandler, null)
{
@@ -45,6 +48,7 @@ internal RunTestsWithTests(IRequestData requestData, IEnumerable testC
{
this.testCases = testCases;
this.executorUriVsTestList = executorUriVsTestList;
+ this.testCaseEventsHandler = testCaseEventsHandler;
}
protected override void BeforeRaisingTestRunComplete(bool exceptionsHitDuringRunTests)
@@ -67,6 +71,31 @@ protected override void InvokeExecutor(LazyExtension
+ /// Sends Session-End event on in-proc datacollectors
+ ///
+ protected override void SendSessionEnd()
+ {
+ this.testCaseEventsHandler?.SendSessionEnd();
+ }
+
+ ///
+ /// Sends Session-Start event on in-proc datacollectors
+ ///
+ protected override void SendSessionStart()
+ {
+ // Send session start with test sources in property bag for session start event args.
+ if (this.testCaseEventsHandler == null)
+ {
+ return;
+ }
+
+ var properties = new Dictionary();
+ properties.Add("TestSources", TestSourcesUtility.GetSources(this.testCases));
+
+ this.testCaseEventsHandler.SendSessionStart(properties);
+ }
+
///
/// Returns the executor Vs TestCase list
///
diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/TestEngine.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/TestEngine.cs
index 0c2009a091..e9fb6bc300 100644
--- a/src/Microsoft.TestPlatform.CrossPlatEngine/TestEngine.cs
+++ b/src/Microsoft.TestPlatform.CrossPlatEngine/TestEngine.cs
@@ -16,6 +16,7 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine
using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client;
using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client.Parallel;
using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.DataCollection;
+ using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Utilities;
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine;
@@ -313,7 +314,7 @@ private IRequestData GetRequestData(bool isTelemetryOptedIn)
/// test sources
private IEnumerable GetSourcesFromTestRunCriteria(TestRunCriteria testRunCriteria)
{
- return testRunCriteria.HasSpecificTests ? testRunCriteria.Tests.Select(tc => tc.Source).Distinct() : testRunCriteria.Sources;
+ return testRunCriteria.HasSpecificTests ? TestSourcesUtility.GetSources(testRunCriteria.Tests) : testRunCriteria.Sources;
}
}
}
diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Utilities/TestSourcesUtility.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Utilities/TestSourcesUtility.cs
new file mode 100644
index 0000000000..52d6c337db
--- /dev/null
+++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Utilities/TestSourcesUtility.cs
@@ -0,0 +1,59 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Utilities
+{
+ using System.Collections.Generic;
+ using System.IO;
+ using System.Linq;
+ using Microsoft.VisualStudio.TestPlatform.ObjectModel;
+
+ ///
+ /// Test sources utility class
+ ///
+ internal class TestSourcesUtility
+ {
+ ///
+ /// Gets test sources from adapter source map
+ ///
+ /// The test list.
+ /// List of test Sources
+ internal static IEnumerable GetSources(Dictionary> adapterSourceMap)
+ {
+ IEnumerable sources = new List();
+ return adapterSourceMap?.Values?.Aggregate(sources, (current, enumerable) => current.Concat(enumerable));
+ }
+
+ ///
+ /// Gets test sources from test case list
+ ///
+ /// The test list.
+ /// List of test Sources
+ internal static IEnumerable GetSources(IEnumerable tests)
+ {
+ return tests?.Select(tc => tc.Source).Distinct();
+ }
+
+ ///
+ /// Gets default code base path for inproc collector from test sources
+ ///
+ /// The test list.
+ /// List of test Sources
+ internal static string GetDefaultCodebasePath(Dictionary> adapterSourceMap)
+ {
+ var source = GetSources(adapterSourceMap)?.FirstOrDefault();
+ return source != null ? Path.GetDirectoryName(source) : null;
+ }
+
+ ///
+ /// Gets default code base path for inproc collector from test sources
+ ///
+ /// The test list.
+ /// List of test Sources
+ internal static string GetDefaultCodebasePath(IEnumerable tests)
+ {
+ var source = GetSources(tests)?.FirstOrDefault();
+ return source != null ? Path.GetDirectoryName(source) : null;
+ }
+ }
+}
diff --git a/src/Microsoft.TestPlatform.ObjectModel/DataCollector/InProcDataCollector/TestSessionStartArgs.cs b/src/Microsoft.TestPlatform.ObjectModel/DataCollector/InProcDataCollector/TestSessionStartArgs.cs
index 34ea97329b..1d51764cc9 100644
--- a/src/Microsoft.TestPlatform.ObjectModel/DataCollector/InProcDataCollector/TestSessionStartArgs.cs
+++ b/src/Microsoft.TestPlatform.ObjectModel/DataCollector/InProcDataCollector/TestSessionStartArgs.cs
@@ -4,12 +4,15 @@
namespace Microsoft.VisualStudio.TestPlatform.ObjectModel.DataCollector.InProcDataCollector
{
using System;
+ using System.Collections.Generic;
///
/// The test session start args.
///
public class TestSessionStartArgs : InProcDataCollectionArgs
{
+ private IDictionary Properties;
+
///
/// Initializes a new instance of the class.
///
@@ -18,6 +21,18 @@ public TestSessionStartArgs()
this.Configuration = String.Empty;
}
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// Properties.
+ ///
+ public TestSessionStartArgs(IDictionary properties)
+ {
+ this.Configuration = String.Empty;
+ this.Properties = properties;
+ }
+
///
/// Initializes a new instance of the class.
///
@@ -33,5 +48,41 @@ public TestSessionStartArgs(string configuration)
/// Gets or sets the configuration.
///
public string Configuration { get; set; }
+
+ ///
+ /// Gets session start properties enumerator
+ ///
+ public IEnumerator> GetProperties()
+ {
+ return this.Properties.GetEnumerator();
+ }
+
+ ///
+ /// Gets property value
+ ///
+ ///
+ /// Property name
+ ///
+ public T GetPropertyValue(string property)
+ {
+ ValidateArg.NotNullOrEmpty(property, "property");
+
+ return this.Properties.ContainsKey(property) ? (T)this.Properties[property] : default(T);
+ }
+
+ ///
+ /// Gets property value
+ ///
+ ///
+ /// Property name
+ ///
+ public object GetPropertyValue(string property)
+ {
+ ValidateArg.NotNullOrEmpty(property, "property");
+
+ this.Properties.TryGetValue(property, out object propertyValue);
+
+ return propertyValue;
+ }
}
}
diff --git a/src/vstest.console/Processors/CollectArgumentProcessor.cs b/src/vstest.console/Processors/CollectArgumentProcessor.cs
index 6eb3454fd2..b7b54e6a67 100644
--- a/src/vstest.console/Processors/CollectArgumentProcessor.cs
+++ b/src/vstest.console/Processors/CollectArgumentProcessor.cs
@@ -7,7 +7,6 @@ namespace Microsoft.VisualStudio.TestPlatform.CommandLine.Processors
using System.Collections.Generic;
using System.Globalization;
-
using Microsoft.VisualStudio.TestPlatform.Common;
using Microsoft.VisualStudio.TestPlatform.Common.Interfaces;
using Microsoft.VisualStudio.TestPlatform.Common.Utilities;
@@ -144,6 +143,32 @@ internal static void EnableDataCollectorUsingFriendlyName(string argument, DataC
}
}
+ ///
+ /// Enables coverlet inproc datacollector
+ ///
+ internal static void EnableCoverletInProcDataCollector(string argument, DataCollectionRunSettings dataCollectionRunSettings)
+ {
+ DataCollectorSettings dataCollectorSettings = null;
+
+ if (!DoesDataCollectorSettingsExist(argument, dataCollectionRunSettings, out dataCollectorSettings))
+ {
+ // Create a new setting with deafult values
+ dataCollectorSettings = new DataCollectorSettings();
+ dataCollectorSettings.FriendlyName = argument;
+ dataCollectorSettings.AssemblyQualifiedName = CoverletConstants.CoverletDataCollectorAssemblyQualifiedName;
+ dataCollectorSettings.CodeBase = CoverletConstants.CoverletDataCollectorCodebase;
+ dataCollectorSettings.IsEnabled = true;
+ dataCollectionRunSettings.DataCollectorSettingsList.Add(dataCollectorSettings);
+ }
+ else
+ {
+ // Set Assembly qualified name and codebase if not already set
+ dataCollectorSettings.AssemblyQualifiedName = dataCollectorSettings.AssemblyQualifiedName ?? CoverletConstants.CoverletDataCollectorAssemblyQualifiedName;
+ dataCollectorSettings.CodeBase = dataCollectorSettings.CodeBase ?? CoverletConstants.CoverletDataCollectorCodebase;
+ dataCollectorSettings.IsEnabled = true;
+ }
+ }
+
private static bool DoesDataCollectorSettingsExist(string friendlyName,
DataCollectionRunSettings dataCollectionRunSettings,
out DataCollectorSettings dataCollectorSettings)
@@ -172,21 +197,49 @@ internal static void AddDataCollectorToRunSettings(string argument, IRunSettings
settings = runSettingsManager.ActiveRunSettings?.SettingsXml;
}
- var dataCollectionRunSettings = XmlRunSettingsUtilities.GetDataCollectionRunSettings(settings);
- if (dataCollectionRunSettings == null)
- {
- dataCollectionRunSettings = new DataCollectionRunSettings();
- }
+ var dataCollectionRunSettings = XmlRunSettingsUtilities.GetDataCollectionRunSettings(settings) ?? new DataCollectionRunSettings();
+ var inProcDataCollectionRunSettings = XmlRunSettingsUtilities.GetInProcDataCollectionRunSettings(settings)
+ ?? new DataCollectionRunSettings(
+ Constants.InProcDataCollectionRunSettingsName,
+ Constants.InProcDataCollectorsSettingName,
+ Constants.InProcDataCollectorSettingName);
// Add data collectors if not already present, enable if already present.
EnableDataCollectorUsingFriendlyName(argument, dataCollectionRunSettings);
runSettingsManager.UpdateRunSettingsNodeInnerXml(Constants.DataCollectionRunSettingsName, dataCollectionRunSettings.ToXml().InnerXml);
+
+ if (string.Equals(argument, CoverletConstants.CoverletDataCollectorFriendlyName, StringComparison.OrdinalIgnoreCase))
+ {
+ // Add inproc data collector to runsetings if coverlet code coverage is enabled
+ EnableCoverletInProcDataCollector(argument, inProcDataCollectionRunSettings);
+ runSettingsManager.UpdateRunSettingsNodeInnerXml(Constants.InProcDataCollectionRunSettingsName, inProcDataCollectionRunSettings.ToXml().InnerXml);
+ }
}
internal static void AddDataCollectorFriendlyName(string friendlyName)
{
EnabledDataCollectors.Add(friendlyName.ToLower());
}
+
+ internal static class CoverletConstants
+ {
+ ///
+ /// Coverlet inproc data collector friendlyname
+ ///
+ public const string CoverletDataCollectorFriendlyName = "XPlat Code Coverage";
+
+ /// TODO : Finalize Name
+ ///
+ /// Coverlet inproc data collector assembly qualified name
+ ///
+ public const string CoverletDataCollectorAssemblyQualifiedName = "Microsoft.TestPlatform.Extensions.CoverletCoverageDataCollector.CoverletCoverageDataCollector, Microsoft.TestPlatform.Extensions.CoverletCoverageDataCollector, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
+
+ /// TODO : Finalize codebase
+ ///
+ /// Coverlet inproc data collector codebase
+ ///
+ public const string CoverletDataCollectorCodebase = "coverletinprocdatacollector.dll";
+ }
}
}
diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/DataCollection/InProcDataCollectionExtensionManagerTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/DataCollection/InProcDataCollectionExtensionManagerTests.cs
index d05285df0b..88d7aa95a5 100644
--- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/DataCollection/InProcDataCollectionExtensionManagerTests.cs
+++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/DataCollection/InProcDataCollectionExtensionManagerTests.cs
@@ -7,10 +7,9 @@ namespace TestPlatform.CrossPlatEngine.UnitTests.DataCollection
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
-
+ using System.Xml;
using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.DataCollection;
using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.DataCollection.Interfaces;
- using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Execution;
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.DataCollection;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.DataCollector.InProcDataCollector;
@@ -37,24 +36,65 @@ public class InProcDataCollectionExtensionManagerTests
";
private Mock mockTestEventsPublisher;
private TestableInProcDataCollectionExtensionManager inProcDataCollectionManager;
+ private string defaultCodebase = "E:\\repos\\MSTest\\src\\managed\\TestPlatform\\TestImpactListener.Tests\\bin\\Debug";
public InProcDataCollectionExtensionManagerTests()
{
this.mockTestEventsPublisher = new Mock();
- this.inProcDataCollectionManager = new TestableInProcDataCollectionExtensionManager(this.settingsXml, this.mockTestEventsPublisher.Object);
+ this.inProcDataCollectionManager = new TestableInProcDataCollectionExtensionManager(this.settingsXml, this.mockTestEventsPublisher.Object, this.defaultCodebase);
}
[TestMethod]
public void InProcDataCollectionExtensionManagerShouldLoadsDataCollectorsFromRunSettings()
{
- var dataCollectorSettings = (inProcDataCollectionManager.InProcDataCollectors.First().Value as MockDataCollector).DataCollectorSettings;
+ var dataCollector = inProcDataCollectionManager.InProcDataCollectors.First().Value as MockDataCollector;
Assert.IsTrue(inProcDataCollectionManager.IsInProcDataCollectionEnabled, "InProcDataCollection must be enabled if runsettings contains inproc datacollectors.");
Assert.AreEqual(inProcDataCollectionManager.InProcDataCollectors.Count, 1, "One Datacollector must be registered");
- Assert.IsTrue(string.Equals(dataCollectorSettings.AssemblyQualifiedName, "TestImpactListener.Tests, Version=1.0.0.0, Culture=neutral, PublicKeyToken=7ccb7239ffde675a", StringComparison.OrdinalIgnoreCase));
- Assert.IsTrue(string.Equals(dataCollectorSettings.CodeBase, @"E:\repos\MSTest\src\managed\TestPlatform\TestImpactListener.Tests\bin\Debug\TestImpactListener.Tests.dll", StringComparison.OrdinalIgnoreCase));
- Assert.IsTrue(string.Equals(dataCollectorSettings.Configuration.OuterXml.ToString(), @"4312", StringComparison.OrdinalIgnoreCase));
+ Assert.IsTrue(string.Equals(dataCollector.AssemblyQualifiedName, "TestImpactListener.Tests, Version=1.0.0.0, Culture=neutral, PublicKeyToken=7ccb7239ffde675a", StringComparison.OrdinalIgnoreCase));
+ Assert.IsTrue(string.Equals(dataCollector.CodeBase, @"E:\repos\MSTest\src\managed\TestPlatform\TestImpactListener.Tests\bin\Debug\TestImpactListener.Tests.dll", StringComparison.OrdinalIgnoreCase));
+ Assert.IsTrue(string.Equals(dataCollector.Configuration.OuterXml.ToString(), @"4312", StringComparison.OrdinalIgnoreCase));
+ }
+
+ [TestMethod]
+ public void InProcDataCollectionExtensionManagerLoadsDataCollectorFromDefaultCodebaseIfCodebaseIsRelative()
+ {
+ string settingsXml = @"
+
+
+
+
+ 4312
+
+
+
+
+ ";
+ this.inProcDataCollectionManager = new TestableInProcDataCollectionExtensionManager(settingsXml, this.mockTestEventsPublisher.Object, this.defaultCodebase);
+
+ var codebase = (inProcDataCollectionManager.InProcDataCollectors.Values.First() as MockDataCollector).CodeBase;
+ Assert.AreEqual(codebase, @"E:\repos\MSTest\src\managed\TestPlatform\TestImpactListener.Tests\bin\Debug\TestImpactListener.Tests.dll");
+ }
+
+ [TestMethod]
+ public void InProcDataCollectionExtensionManagerLoadsDataCollectorFromGivenCodebaseIfCodebaseIsAbsolute()
+ {
+ string settingsXml = @"
+
+
+
+
+ 4312
+
+
+
+
+ ";
+ this.inProcDataCollectionManager = new TestableInProcDataCollectionExtensionManager(settingsXml, this.mockTestEventsPublisher.Object, this.defaultCodebase);
+
+ var codebase = (inProcDataCollectionManager.InProcDataCollectors.Values.First() as MockDataCollector).CodeBase;
+ Assert.AreEqual(codebase, "\\\\DummyPath\\TestImpactListener.Tests.dll");
}
[TestMethod]
@@ -77,31 +117,31 @@ public void InProcDataCollectorIsReadingMultipleDataCollector()
";
- this.inProcDataCollectionManager = new TestableInProcDataCollectionExtensionManager(multiSettingsXml, this.mockTestEventsPublisher.Object);
+ this.inProcDataCollectionManager = new TestableInProcDataCollectionExtensionManager(multiSettingsXml, this.mockTestEventsPublisher.Object, this.defaultCodebase);
bool secondOne = false;
- DataCollectorSettings dataCollectorSettings1 = null;
- DataCollectorSettings dataCollectorSettings2 = null;
+ MockDataCollector dataCollector1 = null;
+ MockDataCollector dataCollector2 = null;
foreach (var inProcDC in inProcDataCollectionManager.InProcDataCollectors.Values)
{
if (secondOne)
{
- dataCollectorSettings2 = (inProcDC as MockDataCollector).DataCollectorSettings;
+ dataCollector2 = inProcDC as MockDataCollector;
}
else
{
- dataCollectorSettings1 = (inProcDC as MockDataCollector).DataCollectorSettings;
+ dataCollector1 = inProcDC as MockDataCollector;
secondOne = true;
}
}
- Assert.IsTrue(string.Equals(dataCollectorSettings1.AssemblyQualifiedName, "TestImpactListener.Tests, Version=1.0.0.0, Culture=neutral, PublicKeyToken=7ccb7239ffde675a", StringComparison.OrdinalIgnoreCase));
- Assert.IsTrue(string.Equals(dataCollectorSettings1.CodeBase, @"E:\repos\MSTest\src\managed\TestPlatform\TestImpactListener.Tests\bin\Debug\TestImpactListener.Tests1.dll", StringComparison.OrdinalIgnoreCase));
- Assert.IsTrue(string.Equals(dataCollectorSettings1.Configuration.OuterXml.ToString(), @"4312", StringComparison.OrdinalIgnoreCase));
+ Assert.IsTrue(string.Equals(dataCollector1.AssemblyQualifiedName, "TestImpactListener.Tests, Version=1.0.0.0, Culture=neutral, PublicKeyToken=7ccb7239ffde675a", StringComparison.OrdinalIgnoreCase));
+ Assert.IsTrue(string.Equals(dataCollector1.CodeBase, @"E:\repos\MSTest\src\managed\TestPlatform\TestImpactListener.Tests\bin\Debug\TestImpactListener.Tests1.dll", StringComparison.OrdinalIgnoreCase));
+ Assert.IsTrue(string.Equals(dataCollector1.Configuration.OuterXml.ToString(), @"4312", StringComparison.OrdinalIgnoreCase));
- Assert.IsTrue(string.Equals(dataCollectorSettings2.AssemblyQualifiedName, "TestImpactListener.Tests, Version=2.0.0.0, Culture=neutral, PublicKeyToken=7ccb7239ffde675a", StringComparison.OrdinalIgnoreCase));
- Assert.IsTrue(string.Equals(dataCollectorSettings2.CodeBase, @"E:\repos\MSTest\src\managed\TestPlatform\TestImpactListener.Tests\bin\Debug\TestImpactListener.Tests2.dll", StringComparison.OrdinalIgnoreCase));
- Assert.IsTrue(string.Equals(dataCollectorSettings2.Configuration.OuterXml.ToString(), @"4313", StringComparison.OrdinalIgnoreCase));
+ Assert.IsTrue(string.Equals(dataCollector2.AssemblyQualifiedName, "TestImpactListener.Tests, Version=2.0.0.0, Culture=neutral, PublicKeyToken=7ccb7239ffde675a", StringComparison.OrdinalIgnoreCase));
+ Assert.IsTrue(string.Equals(dataCollector2.CodeBase, @"E:\repos\MSTest\src\managed\TestPlatform\TestImpactListener.Tests\bin\Debug\TestImpactListener.Tests2.dll", StringComparison.OrdinalIgnoreCase));
+ Assert.IsTrue(string.Equals(dataCollector2.Configuration.OuterXml.ToString(), @"4313", StringComparison.OrdinalIgnoreCase));
}
[TestMethod]
@@ -119,9 +159,24 @@ public void InProcDataCollectionExtensionManagerWillNotEnableDataCollectionForIn
";
- var manager = new InProcDataCollectionExtensionManager(invalidSettingsXml, this.mockTestEventsPublisher.Object);
+ var manager = new InProcDataCollectionExtensionManager(invalidSettingsXml, this.mockTestEventsPublisher.Object, this.defaultCodebase);
Assert.IsFalse(manager.IsInProcDataCollectionEnabled, "InProcDataCollection must be disabled on invalid settings.");
}
+ [TestMethod]
+ public void TriggerSessionStartShouldBeCalledWithCorrectTestSources()
+ {
+ var properties = new Dictionary();
+ properties.Add("TestSources", new List() { "testsource1.dll", "testsource2.dll" });
+
+ var mockDataCollector = inProcDataCollectionManager.InProcDataCollectors.Values.FirstOrDefault() as MockDataCollector;
+
+ this.mockTestEventsPublisher.Raise(x => x.SessionStart += null, new SessionStartEventArgs(properties));
+ Assert.IsTrue((mockDataCollector.TestSessionStartCalled == 1), "TestSessionStart must be called on datacollector");
+
+ Assert.IsTrue(mockDataCollector.TestSources.Contains("testsource1.dll"));
+ Assert.IsTrue(mockDataCollector.TestSources.Contains("testsource2.dll"));
+ }
+
[TestMethod]
public void TriggerSessionStartShouldCallInProcDataCollector()
@@ -179,26 +234,38 @@ public void TriggerTestCaseEndShouldtBeCalledMultipleTimesInDataDrivenScenario()
internal class TestableInProcDataCollectionExtensionManager : InProcDataCollectionExtensionManager
{
- public TestableInProcDataCollectionExtensionManager(string runSettings, ITestEventsPublisher mockTestEventsPublisher) : base(runSettings, mockTestEventsPublisher)
+ public TestableInProcDataCollectionExtensionManager(string runSettings, ITestEventsPublisher mockTestEventsPublisher, string defaultCodebase) : base(runSettings, mockTestEventsPublisher, defaultCodebase)
{
}
- protected override IInProcDataCollector CreateDataCollector(DataCollectorSettings dataCollectorSettings, TypeInfo interfaceTypeInfo)
+ protected override IInProcDataCollector CreateDataCollector(string assemblyQualifiedName, string codebase, XmlElement configuration, TypeInfo interfaceTypeInfo)
{
- return new MockDataCollector(dataCollectorSettings);
+ return new MockDataCollector(assemblyQualifiedName, codebase,configuration);
}
}
public class MockDataCollector : IInProcDataCollector
{
- public MockDataCollector(DataCollectorSettings dataCollectorSettings)
+ public MockDataCollector(string assemblyQualifiedName, string codebase, XmlElement configuration)
+ {
+ this.AssemblyQualifiedName = assemblyQualifiedName;
+ this.CodeBase = codebase;
+ this.Configuration = configuration;
+ }
+
+ public string AssemblyQualifiedName
{
- this.DataCollectorSettings = dataCollectorSettings;
+ get;
+ private set;
}
- public string AssemblyQualifiedName => this.DataCollectorSettings.AssemblyQualifiedName;
+ public string CodeBase
+ {
+ get;
+ private set;
+ }
- public DataCollectorSettings DataCollectorSettings
+ public XmlElement Configuration
{
get;
private set;
@@ -208,6 +275,11 @@ public DataCollectorSettings DataCollectorSettings
public int TestSessionEndCalled { get; private set; }
public int TestCaseStartCalled { get; private set; }
public int TestCaseEndCalled { get; private set; }
+ public IEnumerable TestSources
+ {
+ get;
+ private set;
+ }
public void LoadDataCollector(IDataCollectionSink inProcDataCollectionSink)
{
@@ -218,13 +290,19 @@ public void TriggerInProcDataCollectionMethod(string methodName, InProcDataColle
{
switch (methodName)
{
- case Constants.TestSessionStartMethodName: TestSessionStartCalled++; break;
+ case Constants.TestSessionStartMethodName: this.TestSessionStartMethodCalled(methodArg as TestSessionStartArgs); break;
case Constants.TestSessionEndMethodName: TestSessionEndCalled++; break;
case Constants.TestCaseStartMethodName: TestCaseStartCalled++; break;
case Constants.TestCaseEndMethodName: TestCaseEndCalled++; break;
default: break;
}
}
+
+ private void TestSessionStartMethodCalled(TestSessionStartArgs testSessionStartArgs)
+ {
+ TestSessionStartCalled++;
+ this.TestSources = testSessionStartArgs.GetPropertyValue>("TestSources");
+ }
}
}
}
diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/BaseRunTestsTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/BaseRunTestsTests.cs
index 631b9e99c3..65efe64c15 100644
--- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/BaseRunTestsTests.cs
+++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/BaseRunTestsTests.cs
@@ -93,7 +93,7 @@ public BaseRunTestsTests()
this.mockTestRunEventsHandler.Object,
this.mockTestPlatformEventSource.Object,
null,
- new PlatformThread(),
+ new PlatformThread(),
this.mockDataSerializer.Object);
TestPluginCacheTests.SetupMockExtensions(new string[] { typeof(BaseRunTestsTests).GetTypeInfo().Assembly.Location }, () => { });
@@ -584,7 +584,7 @@ public void RunTestsShouldUpdateActiveTestCasesSourceWithPackageIfTestSourceIsPa
const string package = @"C:\Porjects\UnitTestApp3\Debug\UnitTestApp3\UnitTestApp3.build.appxrecipe";
this.mockDataSerializer.Setup(d => d.Clone(It.IsAny()))
.Returns(t => JsonDataSerializer.Instance.Clone(t));
- this.SetUpTestRunEvents(package, setupHandleTestRunComplete:false);
+ this.SetUpTestRunEvents(package, setupHandleTestRunComplete: false);
// Act.
this.runTestsInstance.RunTests();
@@ -880,7 +880,7 @@ private void SetUpTestRunEvents(string package = null, bool setupHandleTestRunCo
this.mockTestRunEventsHandler.Object,
this.mockTestPlatformEventSource.Object,
null,
- new PlatformThread(),
+ new PlatformThread(),
this.mockDataSerializer.Object);
var assemblyLocation = typeof(BaseRunTestsTests).GetTypeInfo().Assembly.Location;
@@ -978,8 +978,10 @@ public TestableBaseRunTests(
platformThread,
dataSerializer)
{
+ this.testCaseEventsHandler = testCaseEventsHandler;
}
+ private ITestCaseEventsHandler testCaseEventsHandler;
public Action BeforeRaisingTestRunCompleteCallback { get; set; }
@@ -1033,6 +1035,16 @@ protected override void InvokeExecutor(LazyExtension { { "TestSources", new List() { "1.dll" } } });
+ }
}
[ExtensionUri(BaseRunTestsExecutorUri)]
diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/RunTestsWithSourcesTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/RunTestsWithSourcesTests.cs
index d761559f3b..fe552fa4ce 100644
--- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/RunTestsWithSourcesTests.cs
+++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/RunTestsWithSourcesTests.cs
@@ -253,6 +253,50 @@ public void RunTestsShouldLogWarningOnNoTestsAvailableInAssemblyWithLongTestCase
this.mockTestRunEventsHandler.Verify(treh => treh.HandleLogMessage(TestMessageLevel.Warning, expectedMessage), Times.Once);
}
+ [TestMethod]
+ public void SendSessionStartShouldCallSessionStartWithCorrectTestSources()
+ {
+ var adapterSourceMap = new Dictionary>();
+ adapterSourceMap.Add("a", new List { "1.dll", "2.dll" });
+ var mockTestCaseEventsHandler = new Mock();
+
+ this.runTestsInstance = new TestableRunTestsWithSources(
+ adapterSourceMap,
+ null,
+ testExecutionContext,
+ mockTestCaseEventsHandler.Object,
+ this.mockTestRunEventsHandler.Object,
+ this.mockRequestData.Object);
+
+ this.runTestsInstance.CallSendSessionStart();
+
+ mockTestCaseEventsHandler.Verify(x => x.SendSessionStart(It.Is>(
+ y => y.ContainsKey("TestSources")
+ && ((IEnumerable)y["TestSources"]).Contains("1.dll")
+ && ((IEnumerable)y["TestSources"]).Contains("2.dll")
+ )));
+ }
+
+ [TestMethod]
+ public void SendSessionEndShouldCallSessionEnd()
+ {
+ var adapterSourceMap = new Dictionary>();
+ adapterSourceMap.Add("a", new List { "1.dll", "2.dll" });
+ var mockTestCaseEventsHandler = new Mock();
+
+ this.runTestsInstance = new TestableRunTestsWithSources(
+ adapterSourceMap,
+ null,
+ testExecutionContext,
+ mockTestCaseEventsHandler.Object,
+ this.mockTestRunEventsHandler.Object,
+ this.mockRequestData.Object);
+
+ this.runTestsInstance.CallSendSessionEnd();
+
+ mockTestCaseEventsHandler.Verify(x => x.SendSessionEnd());
+ }
+
private void SetupForNoTestsAvailable(string testCaseFilter, out string sourcesString)
{
var testAssemblyLocation = typeof(TestCase).GetTypeInfo().Assembly.Location;
@@ -305,6 +349,16 @@ public IEnumerable> CallGetExecutorUriExtensionMap(
return this.GetExecutorUriExtensionMap(testExecutorFrameworkHandle, runContext);
}
+ public void CallSendSessionStart()
+ {
+ this.SendSessionStart();
+ }
+
+ public void CallSendSessionEnd()
+ {
+ this.SendSessionEnd();
+ }
+
public void CallInvokeExecutor(LazyExtension executor,
Tuple executorUriExtensionTuple, RunContext runContext, IFrameworkHandle frameworkHandle)
{
diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/RunTestsWithTestsTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/RunTestsWithTestsTests.cs
index 00177044ed..ee729317c8 100644
--- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/RunTestsWithTestsTests.cs
+++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/RunTestsWithTestsTests.cs
@@ -146,6 +146,53 @@ public void InvokeExecutorShouldInvokeTestExecutorWithTheTests()
CollectionAssert.AreEqual(tests, receivedTests.ToList());
}
+ [TestMethod]
+ public void SendSessionStartShouldCallSessionStartWithCorrectTestSources()
+ {
+ var tests = new List
+ {
+ new TestCase("A.C.M1", new Uri("e://d"), "s.dll")
+ };
+ var mockTestCaseEventsHandler = new Mock();
+
+ this.runTestsInstance = new TestableRunTestsWithTests(
+ tests,
+ null,
+ testExecutionContext,
+ mockTestCaseEventsHandler.Object,
+ this.mockTestRunEventsHandler.Object,
+ this.mockRequestData.Object);
+
+ this.runTestsInstance.CallSendSessionStart();
+
+ mockTestCaseEventsHandler.Verify(x => x.SendSessionStart(It.Is>(
+ y => y.ContainsKey("TestSources")
+ && ((IEnumerable)y["TestSources"]).Contains("s.dll")
+ )));
+ }
+
+ [TestMethod]
+ public void SendSessionEndShouldCallSessionEnd()
+ {
+ var tests = new List
+ {
+ new TestCase("A.C.M1", new Uri("e://d"), "s.dll")
+ };
+ var mockTestCaseEventsHandler = new Mock();
+
+ this.runTestsInstance = new TestableRunTestsWithTests(
+ tests,
+ null,
+ testExecutionContext,
+ mockTestCaseEventsHandler.Object,
+ this.mockTestRunEventsHandler.Object,
+ this.mockRequestData.Object);
+
+ this.runTestsInstance.CallSendSessionEnd();
+
+ mockTestCaseEventsHandler.Verify(x => x.SendSessionEnd());
+ }
+
#region Testable Implemetations
private class TestableRunTestsWithTests : RunTestsWithTests
@@ -177,6 +224,16 @@ public void CallInvokeExecutor(LazyExtension>();
+ adapterSourceMap.Add("adapter1", new List() { "source1.dll", "source2.dll" });
+ adapterSourceMap.Add("adapter2", new List() { "source1.dll", "source3.dll" });
+ adapterSourceMap.Add("adapter3", new List() { "source1.dll"});
+
+ var sources = TestSourcesUtility.GetSources(adapterSourceMap);
+ Assert.AreEqual(sources.Count(), 5);
+ Assert.IsTrue(sources.Contains("source1.dll"));
+ Assert.IsTrue(sources.Contains("source2.dll"));
+ Assert.IsTrue(sources.Contains("source3.dll"));
+ }
+
+ [TestMethod]
+ public void GetSourcesShouldGetDistinctSourcesFromTestCases()
+ {
+ var tests = new List() { new TestCase("test1", new Uri("e://d"), "source1.dll"),
+ new TestCase("test2", new Uri("e://d"), "source2.dll"),
+ new TestCase("test3", new Uri("e://d"), "source1.dll")};
+
+ var sources = TestSourcesUtility.GetSources(tests);
+ Assert.AreEqual(sources.Count(), 2);
+ Assert.IsTrue(sources.Contains("source1.dll"));
+ Assert.IsTrue(sources.Contains("source2.dll"));
+ }
+
+ [TestMethod]
+ public void GetDefaultCodeBasePathShouldReturnNullIfAdapterSourceMapIsEmpty()
+ {
+ var adapterSourceMap = new Dictionary>();
+
+ var defaultCodeBase = TestSourcesUtility.GetDefaultCodebasePath(adapterSourceMap);
+ Assert.IsNull(defaultCodeBase);
+ }
+
+ [TestMethod]
+ public void GetDefaultCodeBasePathShouldReturnNullIfTestCaseListIsEmpty()
+ {
+ var tests = new List();
+
+ var defaultCodeBase = TestSourcesUtility.GetDefaultCodebasePath(tests);
+ Assert.IsNull(defaultCodeBase);
+ }
+
+ [TestMethod]
+ public void GetDefaultCodeBasePathShouldReturnDefaultDirectoryPathForAdapterSourceMap()
+ {
+ var adapterSourceMap = new Dictionary>();
+ adapterSourceMap.Add("adapter1", new List() { "c:\\folder1\\source1.dll", "c:\\folder2\\source2.dll" });
+
+ var defaultCodeBase = TestSourcesUtility.GetDefaultCodebasePath(adapterSourceMap);
+ Assert.AreEqual(defaultCodeBase, "c:\\folder1");
+ }
+
+ [TestMethod]
+ public void GetDefaultCodeBasePathShouldReturnDefaultDirectoryPathForTestCaseList()
+ {
+ var tests = new List() { new TestCase("test1", new Uri("e://d"), "c:\\folder1\\source1.dll") };
+
+ var defaultCodeBase = TestSourcesUtility.GetDefaultCodebasePath(tests);
+ Assert.AreEqual(defaultCodeBase, "c:\\folder1");
+ }
+ }
+}
diff --git a/test/vstest.console.UnitTests/Processors/CollectArgumentProcessorTests.cs b/test/vstest.console.UnitTests/Processors/CollectArgumentProcessorTests.cs
index ee7eba7fd6..70651d5c97 100644
--- a/test/vstest.console.UnitTests/Processors/CollectArgumentProcessorTests.cs
+++ b/test/vstest.console.UnitTests/Processors/CollectArgumentProcessorTests.cs
@@ -10,6 +10,7 @@ namespace vstest.console.UnitTests.Processors
using Microsoft.VisualStudio.TestPlatform.Common;
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using static Microsoft.VisualStudio.TestPlatform.CommandLine.Processors.CollectArgumentExecutor;
[TestClass]
public class CollectArgumentProcessorTests
@@ -176,6 +177,83 @@ public void InitializeShouldEnableMultipleCollectorsWhenCalledMoreThanOnce()
Assert.AreEqual("\r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n", this.settingsProvider.ActiveRunSettings.SettingsXml);
}
+ [TestMethod]
+ public void InitializeShouldAddOutProcAndInprocCollectorWhenXPlatCodeCoverageIsEnabled()
+ {
+ var runsettingsString = string.Format(DefaultRunSettings, string.Empty);
+ var runsettings = new RunSettings();
+ runsettings.LoadSettingsXml(runsettingsString);
+ this.settingsProvider.SetActiveRunSettings(runsettings);
+ this.executor.Initialize("XPlat Code Coverage");
+
+ Assert.AreEqual($"\r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n", this.settingsProvider.ActiveRunSettings.SettingsXml);
+ }
+
+ [TestMethod]
+ public void InitializeXPlatCodeCoverageShouldNotChangeExistingDataCollectors()
+ {
+ var runsettingsString = "\r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n";
+ runsettingsString = string.Format(runsettingsString, string.Empty);
+ var runsettings = new RunSettings();
+ runsettings.LoadSettingsXml(runsettingsString);
+ this.settingsProvider.SetActiveRunSettings(runsettings);
+ this.executor.Initialize("XPlat Code Coverage");
+
+ Assert.AreEqual($"\r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n", this.settingsProvider.ActiveRunSettings.SettingsXml);
+ }
+
+ [TestMethod]
+ public void InitializeXPlatCodeCoverageShouldNotChangeExistingXPlatDataCollectorSetting()
+ {
+ var runsettingsString = "\r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n ";
+ runsettingsString = string.Format(runsettingsString, string.Empty);
+ var runsettings = new RunSettings();
+ runsettings.LoadSettingsXml(runsettingsString);
+ this.settingsProvider.SetActiveRunSettings(runsettings);
+ this.executor.Initialize("XPlat Code Coverage");
+
+ Assert.AreEqual("\r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n", this.settingsProvider.ActiveRunSettings.SettingsXml);
+ }
+
+ [TestMethod]
+ public void InitializeXPlatCodeCoverageShouldNotChangeExistingXPlatInProcDataCollectorSetting()
+ {
+ var runsettingsString = "\r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n";
+ runsettingsString = string.Format(runsettingsString, string.Empty);
+ var runsettings = new RunSettings();
+ runsettings.LoadSettingsXml(runsettingsString);
+ this.settingsProvider.SetActiveRunSettings(runsettings);
+ this.executor.Initialize("XPlat Code Coverage");
+
+ Assert.AreEqual("\r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n", this.settingsProvider.ActiveRunSettings.SettingsXml);
+ }
+
+ [TestMethod]
+ public void InitializeXPlatCodeCoverageShouldAddXPlatOutProcProcDataCollectorSetting()
+ {
+ var runsettingsString = $"\r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n";
+ runsettingsString = string.Format(runsettingsString, string.Empty);
+ var runsettings = new RunSettings();
+ runsettings.LoadSettingsXml(runsettingsString);
+ this.settingsProvider.SetActiveRunSettings(runsettings);
+ this.executor.Initialize("XPlat Code Coverage");
+
+ Assert.AreEqual($"\r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n", this.settingsProvider.ActiveRunSettings.SettingsXml);
+ }
+
+ [TestMethod]
+ public void InitializeXPlatCodeCoverageShouldAddXPlatInProcProcDataCollectoPropertiesIfNotPresent()
+ {
+ var runsettingsString = $"\r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n";
+ runsettingsString = string.Format(runsettingsString, string.Empty);
+ var runsettings = new RunSettings();
+ runsettings.LoadSettingsXml(runsettingsString);
+ this.settingsProvider.SetActiveRunSettings(runsettings);
+ this.executor.Initialize("XPlat Code Coverage");
+
+ Assert.AreEqual($"\r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n", this.settingsProvider.ActiveRunSettings.SettingsXml);
+ }
+
#endregion
}
}