Skip to content

Commit 6933f0b

Browse files
authored
Adapter should honour DesignMode flag (#205)
* Adapter should honour DesignMode flag * PR comments * PR comments
1 parent 884ad2d commit 6933f0b

File tree

8 files changed

+482
-100
lines changed

8 files changed

+482
-100
lines changed

src/Adapter/MSTest.CoreAdapter/Discovery/UnitTestDiscoverer.cs

Lines changed: 42 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ namespace Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter
55
{
66
using System.Collections.Generic;
77
using Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.Discovery;
8+
using Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.Helpers;
89
using Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.ObjectModel;
910
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter;
1011
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging;
@@ -80,58 +81,62 @@ internal virtual void DiscoverTestsInSource(
8081

8182
internal void SendTestCases(string source, IEnumerable<UnitTestElement> testElements, ITestCaseDiscoverySink discoverySink)
8283
{
84+
var isDesignMode = RunConfigurationSettings.ConfigurationSettings.DesignMode;
85+
8386
var navigationSessions = new Dictionary<string, object>();
8487
try
8588
{
86-
navigationSessions.Add(source, PlatformServiceProvider.Instance.FileOperations.CreateNavigationSession(source));
89+
if (isDesignMode)
90+
{
91+
navigationSessions.Add(source, PlatformServiceProvider.Instance.FileOperations.CreateNavigationSession(source));
92+
}
8793

8894
foreach (var testElement in testElements)
8995
{
90-
string testSource = testElement.TestMethod.DeclaringAssemblyName ?? source;
9196
object testNavigationSession;
92-
93-
if (navigationSessions.ContainsKey(testSource))
94-
{
95-
testNavigationSession = navigationSessions[testSource];
96-
}
97-
else
98-
{
99-
testNavigationSession = PlatformServiceProvider.Instance.FileOperations.CreateNavigationSession(testSource);
100-
navigationSessions.Add(testSource, testNavigationSession);
101-
}
102-
10397
var testCase = testElement.ToTestCase();
10498

105-
if (testNavigationSession != null)
99+
if (isDesignMode)
106100
{
107-
var className = testElement.TestMethod.DeclaringClassFullName
108-
?? testElement.TestMethod.FullClassName;
109-
110-
var methodName = testElement.TestMethod.Name;
101+
string testSource = testElement.TestMethod.DeclaringAssemblyName ?? source;
111102

112-
// If it is async test method use compiler generated type and method name for navigation data.
113-
if (!string.IsNullOrEmpty(testElement.AsyncTypeName))
103+
if (!navigationSessions.TryGetValue(testSource, out testNavigationSession))
114104
{
115-
className = testElement.AsyncTypeName;
116-
117-
// compiler generated method name is "MoveNext".
118-
methodName = "MoveNext";
105+
testNavigationSession = PlatformServiceProvider.Instance.FileOperations.CreateNavigationSession(testSource);
106+
navigationSessions.Add(testSource, testNavigationSession);
119107
}
120108

121-
int minLineNumber;
122-
string fileName;
123-
124-
PlatformServiceProvider.Instance.FileOperations.GetNavigationData(
125-
testNavigationSession,
126-
className,
127-
methodName,
128-
out minLineNumber,
129-
out fileName);
130-
131-
if (!string.IsNullOrEmpty(fileName))
109+
if (testNavigationSession != null)
132110
{
133-
testCase.LineNumber = minLineNumber;
134-
testCase.CodeFilePath = fileName;
111+
var className = testElement.TestMethod.DeclaringClassFullName
112+
?? testElement.TestMethod.FullClassName;
113+
114+
var methodName = testElement.TestMethod.Name;
115+
116+
// If it is async test method use compiler generated type and method name for navigation data.
117+
if (!string.IsNullOrEmpty(testElement.AsyncTypeName))
118+
{
119+
className = testElement.AsyncTypeName;
120+
121+
// compiler generated method name is "MoveNext".
122+
methodName = "MoveNext";
123+
}
124+
125+
int minLineNumber;
126+
string fileName;
127+
128+
PlatformServiceProvider.Instance.FileOperations.GetNavigationData(
129+
testNavigationSession,
130+
className,
131+
methodName,
132+
out minLineNumber,
133+
out fileName);
134+
135+
if (!string.IsNullOrEmpty(fileName))
136+
{
137+
testCase.LineNumber = minLineNumber;
138+
testCase.CodeFilePath = fileName;
139+
}
135140
}
136141
}
137142

src/Adapter/MSTest.CoreAdapter/Helpers/RunSettingsUtilities.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,8 @@ private static T GetNodeValue<T>(string settingsXml, string nodeName, Func<XmlRe
9090

9191
if (!reader.EOF)
9292
{
93-
// read nodeName element.
94-
return nodeParser(reader);
93+
// read nodeName element.
94+
return nodeParser(reader);
9595
}
9696
}
9797
}

src/Adapter/MSTest.CoreAdapter/MSTest.CoreAdapter.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
<DesignTime>True</DesignTime>
8181
<DependentUpon>Resource.resx</DependentUpon>
8282
</Compile>
83+
<Compile Include="RunConfigurationSettings.cs" />
8384
</ItemGroup>
8485
<ItemGroup>
8586
<ProjectReference Include="..\..\TestFramework\Extension.Core\Extension.Core.csproj">

src/Adapter/MSTest.CoreAdapter/MSTestDiscoverer.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public void DiscoverTests(
4747

4848
// Populate the runsettings.
4949
MSTestSettings.PopulateSettings(discoveryContext);
50+
RunConfigurationSettings.PopulateSettings(discoveryContext);
5051

5152
// Scenarios that include testsettings or forcing a run via the legacy adapter are currently not supported in MSTestAdapter.
5253
if (MSTestSettings.IsLegacyScenario(logger))
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
namespace Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter
5+
{
6+
using System;
7+
using System.IO;
8+
using System.Xml;
9+
10+
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
11+
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter;
12+
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging;
13+
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Utilities;
14+
15+
public class RunConfigurationSettings
16+
{
17+
/// <summary>
18+
/// The settings name.
19+
/// </summary>
20+
public const string SettingsName = "RunConfiguration";
21+
22+
/// <summary>
23+
/// Member variable for RunConfiguration settings
24+
/// </summary>
25+
private static RunConfigurationSettings configurationSettings;
26+
27+
/// <summary>
28+
/// Initializes a new instance of the <see cref="RunConfigurationSettings"/> class.
29+
/// </summary>
30+
public RunConfigurationSettings()
31+
{
32+
this.DesignMode = true;
33+
}
34+
35+
/// <summary>
36+
/// Gets the current settings.
37+
/// </summary>
38+
public static RunConfigurationSettings ConfigurationSettings
39+
{
40+
get
41+
{
42+
if (configurationSettings == null)
43+
{
44+
configurationSettings = new RunConfigurationSettings();
45+
}
46+
47+
return configurationSettings;
48+
}
49+
50+
private set
51+
{
52+
configurationSettings = value;
53+
}
54+
}
55+
56+
/// <summary>
57+
/// Gets a value indicating whether designMode is on(IDE scenario) or off(CLI scenario).
58+
/// </summary>
59+
public bool DesignMode { get; private set; }
60+
61+
/// <summary>
62+
/// Populate adapter settings from the context
63+
/// </summary>
64+
/// <param name="context">
65+
/// The discovery context that contains the runsettings.
66+
/// </param>
67+
public static void PopulateSettings(IDiscoveryContext context)
68+
{
69+
if (context == null || context.RunSettings == null || string.IsNullOrEmpty(context.RunSettings.SettingsXml))
70+
{
71+
// This will contain default adapter settings
72+
ConfigurationSettings = new RunConfigurationSettings();
73+
return;
74+
}
75+
76+
var settings = GetSettings(context.RunSettings.SettingsXml, SettingsName);
77+
78+
if (settings != null)
79+
{
80+
ConfigurationSettings = settings;
81+
return;
82+
}
83+
84+
ConfigurationSettings = new RunConfigurationSettings();
85+
}
86+
87+
/// <summary>
88+
/// Gets the adapter specific settings from the xml.
89+
/// </summary>
90+
/// <param name="runsettingsXml"> The xml with the settings passed from the test platform. </param>
91+
/// <param name="settingName"> The name of the adapter settings to fetch - Its either MSTest or MSTestV2 </param>
92+
/// <returns> The settings if found. Null otherwise. </returns>
93+
internal static RunConfigurationSettings GetSettings(string runsettingsXml, string settingName)
94+
{
95+
using (var stringReader = new StringReader(runsettingsXml))
96+
{
97+
XmlReader reader = XmlReader.Create(stringReader, XmlRunSettingsUtilities.ReaderSettings);
98+
99+
// read to the fist child
100+
XmlReaderUtilities.ReadToRootNode(reader);
101+
reader.ReadToNextElement();
102+
103+
// Read till we reach nodeName element or reach EOF
104+
while (!string.Equals(reader.Name, settingName, StringComparison.OrdinalIgnoreCase)
105+
&&
106+
!reader.EOF)
107+
{
108+
reader.SkipToNextElement();
109+
}
110+
111+
if (!reader.EOF)
112+
{
113+
// read nodeName element.
114+
return ToSettings(reader.ReadSubtree());
115+
}
116+
}
117+
118+
return null;
119+
}
120+
121+
/// <summary>
122+
/// Resets any settings loaded.
123+
/// </summary>
124+
internal static void Reset()
125+
{
126+
RunConfigurationSettings.ConfigurationSettings = null;
127+
}
128+
129+
/// <summary>
130+
/// Convert the parameter xml to TestSettings
131+
/// </summary>
132+
/// <param name="reader">Reader to load the settings from.</param>
133+
/// <returns>An instance of the <see cref="MSTestSettings"/> class</returns>
134+
private static RunConfigurationSettings ToSettings(XmlReader reader)
135+
{
136+
ValidateArg.NotNull<XmlReader>(reader, "reader");
137+
138+
// Expected format of the xml is: -
139+
//
140+
// <Runsettings>
141+
// <RunConfiguration>
142+
// <DesignMode>true</DesignMode>
143+
// </RunConfiguration>
144+
// </Runsettings>
145+
RunConfigurationSettings settings = new RunConfigurationSettings();
146+
147+
// Read the first element in the section which is either "MSTest"/"MSTestV2"
148+
reader.ReadToNextElement();
149+
150+
if (!reader.IsEmptyElement)
151+
{
152+
reader.Read();
153+
154+
while (reader.NodeType == XmlNodeType.Element)
155+
{
156+
bool result;
157+
string elementName = reader.Name.ToUpperInvariant();
158+
switch (elementName)
159+
{
160+
case "DESIGNMODE":
161+
{
162+
if (bool.TryParse(reader.ReadInnerXml(), out result))
163+
{
164+
settings.DesignMode = result;
165+
PlatformServiceProvider.Instance.AdapterTraceLogger.LogInfo(
166+
"DesignMode value Found : {0} ",
167+
result);
168+
}
169+
170+
break;
171+
}
172+
173+
default:
174+
{
175+
reader.SkipToNextElement();
176+
break;
177+
}
178+
}
179+
}
180+
}
181+
182+
return settings;
183+
}
184+
}
185+
}

0 commit comments

Comments
 (0)