Removed the check to verify if traits are supported by reflection method.
Thus this will not work with older object models.
MODIFY
NuGet.Config
NuGet.Config
<add key="AppVeyor NUnit CI Feed" value="https://ci.appveyor.com/nuget/nunit" />
<add key="AppVeyor NUnit Engine CI Feed" value="https://ci.appveyor.com/nuget/nunit-console" />
<add key="NUnit MyGet Feed" value="https://www.myget.org/F/nunit/api/v2" />
+ <add key="api.nuget.org" value="https://api.nuget.org/v3/index.json" />
</packageSources>
</configuration>

MODIFY
src/NUnitTestAdapter/NUnit.TestAdapter.csproj
src/NUnitTestAdapter/NUnit.TestAdapter.csproj
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net35'">
- <PackageReference Include="Microsoft.VisualStudio.TestPlatform.ObjectModel" Version="0.0.3" PrivateAssets="All" />
+ <PackageReference Include="Microsoft.TestPlatform.ObjectModel" Version="11.0.0" PrivateAssets="All" />
<PackageReference Include="Mono.Cecil" Version="0.9.6.4" />
<PackageReference Include="nunit.engine" Version="3.7.0" PrivateAssets="All" />
</ItemGroup>

MODIFY
src/NUnitTestAdapter/TestConverter.cs
src/NUnitTestAdapter/TestConverter.cs
@@ -39,7 +39,7 @@ namespace NUnit.VisualStudio.TestAdapter
private readonly string _sourceAssembly;
private NavigationDataProvider _navigationDataProvider;
private bool _collectSourceInformation;
- private IDictionary<string, List<KeyValuePair<string, string>>> _attributesCache;
+ private IDictionary<string, List<Trait>> _attributesCache;
#region Constructor
@@ -49,7 +49,7 @@ namespace NUnit.VisualStudio.TestAdapter
_sourceAssembly = sourceAssembly;
_vsTestCaseMap = new Dictionary<string, TestCase>();
_collectSourceInformation = collectSourceInformation;
- _attributesCache = new Dictionary<string, List<KeyValuePair<string, string>>>();
+ _attributesCache = new Dictionary<string, List<Trait>>();
if (_collectSourceInformation)
{
@@ -59,7 +59,7 @@ namespace NUnit.VisualStudio.TestAdapter
#endregion
- public IDictionary<string, List<KeyValuePair<string, string>>> AttributesCache
+ public IDictionary<string, List<Trait>> AttributesCache
{
get
{

MODIFY
src/NUnitTestAdapter/TraitsFeature.cs
src/NUnitTestAdapter/TraitsFeature.cs
@@ -32,60 +32,17 @@ namespace NUnit.VisualStudio.TestAdapter
{
public static class TraitsFeature
{
- private static readonly PropertyInfo TraitsProperty;
- private static readonly MethodInfo TraitsCollectionAdd;
- private static readonly PropertyInfo NameProperty;
- private static readonly PropertyInfo ValueProperty;
-
- static TraitsFeature()
- {
- System.Diagnostics.Debugger.Launch();
- TraitsProperty = typeof(TestCase).GetProperty("Traits");
- if (TraitsProperty != null)
- {
-
- var traitsCollectionType = TraitsProperty.PropertyType;
- TraitsCollectionAdd = traitsCollectionType.GetMethod("Add", new[] { typeof(string), typeof(string) });
-
- var traitType = Type.GetType("Microsoft.VisualStudio.TestPlatform.ObjectModel.Trait,Microsoft.VisualStudio.TestPlatform.ObjectModel");
- if (traitType != null)
- {
- NameProperty = traitType.GetProperty("Name");
- ValueProperty = traitType.GetProperty("Value");
- }
- }
-
- IsSupported = TraitsProperty != null && NameProperty != null && ValueProperty != null;
- }
-
- public static bool IsSupported { get; private set; }
-
public static void AddTrait(this TestCase testCase, string name, string value)
{
- if (TraitsCollectionAdd != null)
+ if(testCase != null)
{
- object traitsCollection = TraitsProperty.GetValue(testCase, new object[0]);
- TraitsCollectionAdd.Invoke(traitsCollection, new object[] { name, value });
+ testCase.Traits.Add(new Trait(name, value));
}
}
- public static void AddTraitsFromTestNode(this TestCase testCase, XmlNode testNode, IDictionary<string,List<KeyValuePair<string,string>>> propertiesCache)
- {
- if (IsSupported)
+ public static void AddTraitsFromTestNode(this TestCase testCase, XmlNode testNode, IDictionary<string,List<Trait>> propertiesCache)
{
- AddTraitsFromTestNode(testNode, TraitsProperty.GetValue(testCase, new object[0]), propertiesCache);
- }
- }
-
- private static bool IsInternalProperty(string propertyName, string propertyValue)
- {
- // Property names starting with '_' are for internal use only
- return string.IsNullOrEmpty(propertyName) || propertyName[0] == '_' || string.IsNullOrEmpty(propertyValue);
- }
-
- private static void AddTraitsFromTestNode(XmlNode test, object traitsCollection, IDictionary<string, List<KeyValuePair<string, string>>> propertiesCache)
- {
- var ancestor = test.ParentNode;
+ var ancestor = testNode.ParentNode;
var key = ancestor.Attributes?["id"]?.Value;
// Reading ancestor properties of a test-case node. And cacheing it.
@@ -93,10 +50,7 @@ namespace NUnit.VisualStudio.TestAdapter
{
if (propertiesCache.ContainsKey(key))
{
- foreach (var property in propertiesCache[key])
- {
- TraitsCollectionAdd.Invoke(traitsCollection, new object[] { property.Key, property.Value });
- }
+ testCase.Traits.AddRange(propertiesCache[key]);
}
else
{
@@ -109,13 +63,13 @@ namespace NUnit.VisualStudio.TestAdapter
AddAttributesToCache(propertiesCache, key, propertyName, propertyValue);
if (!IsInternalProperty(propertyName, propertyValue))
{
- TraitsCollectionAdd.Invoke(traitsCollection, new object[] { propertyName, propertyValue });
+ testCase.Traits.Add(new Trait(propertyName, propertyValue));
}
}
// Adding empty list to dictionary, so that we will not make SelectNodes call again.
if (nodesList.Count == 0 && !propertiesCache.ContainsKey(key))
{
- propertiesCache[key] = new List<KeyValuePair<string, string>>();
+ propertiesCache[key] = new List<Trait>();
}
}
ancestor = ancestor.ParentNode;
@@ -123,32 +77,38 @@ namespace NUnit.VisualStudio.TestAdapter
}
// No Need to store test-case properties in dictionary.
- foreach (XmlNode propertyNode in test.SelectNodes("properties/property"))
+ foreach (XmlNode propertyNode in testNode.SelectNodes("properties/property"))
{
string propertyName = propertyNode.GetAttribute("name");
string propertyValue = propertyNode.GetAttribute("value");
if (!IsInternalProperty(propertyName, propertyValue))
{
- TraitsCollectionAdd.Invoke(traitsCollection, new object[] { propertyName, propertyValue });
+ testCase.Traits.Add(new Trait(propertyName, propertyValue));
}
}
}
- private static void AddAttributesToCache(IDictionary<string, List<KeyValuePair<string, string>>> propertiesCache, string key, string propertyName, string propertyValue)
+ private static bool IsInternalProperty(string propertyName, string propertyValue)
+ {
+ // Property names starting with '_' are for internal use only
+ return string.IsNullOrEmpty(propertyName) || propertyName[0] == '_' || string.IsNullOrEmpty(propertyValue);
+ }
+
+ private static void AddAttributesToCache(IDictionary<string, List<Trait>> propertiesCache, string key, string propertyName, string propertyValue)
{
if (propertiesCache.ContainsKey(key) && !IsInternalProperty(propertyName, propertyValue))
{
- propertiesCache[key].Add(new KeyValuePair<string, string>(propertyName, propertyValue));
+ propertiesCache[key].Add(new Trait(propertyName, propertyValue));
}
else
{
- var kps = new List<KeyValuePair<string, string>>();
+ var traits = new List<Trait>();
if (!IsInternalProperty(propertyName, propertyValue))
{
- kps.Add(new KeyValuePair<string, string>(propertyName, propertyValue));
+ traits.Add(new Trait(propertyName, propertyValue));
}
- propertiesCache[key] = kps;
+ propertiesCache[key] = traits;
}
}
@@ -156,14 +116,10 @@ namespace NUnit.VisualStudio.TestAdapter
{
var traits = new List<NTrait>();
- if (IsSupported)
+ if (testCase != null && testCase.Traits != null)
{
- var traitsCollection = TraitsProperty.GetValue(testCase, new object[0]) as IEnumerable<object>;
-
- if (traitsCollection != null)
- traits.AddRange(from traitObject in traitsCollection let name = NameProperty.GetValue(traitObject, new object[0]) as string let value = ValueProperty.GetValue(traitObject, new object[0]) as string select new NTrait(name, value));
+ traits.AddRange(from trait in testCase.Traits let name = trait.Name let value = trait.Value select new NTrait(name, value));
}
-
return traits;
}
}

MODIFY
src/NUnitTestAdapterTests/NUnit.TestAdapter.Tests.csproj
src/NUnitTestAdapterTests/NUnit.TestAdapter.Tests.csproj
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net45' ">
- <PackageReference Include="Microsoft.VisualStudio.TestPlatform.ObjectModel" Version="0.0.3" PrivateAssets="All" />
+ <PackageReference Include="Microsoft.TestPlatform.ObjectModel" Version="11.0.0" PrivateAssets="All" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp1.0' ">

MODIFY
src/NUnitTestAdapterTests/TestConverterTests.cs
src/NUnitTestAdapterTests/TestConverterTests.cs
@@ -62,10 +62,12 @@ namespace NUnit.VisualStudio.TestAdapter.Tests
var testCase = testConverter.ConvertTestCase(fakeTestNode);
CheckTestCase(testCase);
- if(TraitsFeature.IsSupported)
- {
- Assert.That(testConverter.AttributesCache.Keys.Count, Is.EqualTo(2));
- }
+
+ Assert.That(testConverter.AttributesCache.Keys.Count, Is.EqualTo(1));
+ Assert.That(testConverter.AttributesCache["121"].Count, Is.EqualTo(1));
+ var parentTrait = testConverter.AttributesCache["121"];
+ Assert.That(parentTrait[0].Name, Is.EqualTo("Category"));
+ Assert.That(parentTrait[0].Value, Is.EqualTo("super"));
}
[Test]
@@ -116,14 +118,8 @@ namespace NUnit.VisualStudio.TestAdapter.Tests
Assert.That(testCase.LineNumber, Is.EqualTo(FakeTestData.LineNumber));
}
- // Check traits using reflection, since the feature was added
- // in an update to VisualStudio and may not be present.
- if (TraitsFeature.IsSupported)
- {
var traitList = testCase.GetTraits().Select(trait => trait.Name + ":" + trait.Value).ToList();
-
Assert.That(traitList, Is.EquivalentTo(new[] { "Category:super", "Category:cat1", "Priority:medium" }));
}
}
}
-}

MODIFY
src/NUnitTestAdapterTests/TestTFSBuild.cs
src/NUnitTestAdapterTests/TestTFSBuild.cs
@@ -45,8 +45,6 @@ namespace NUnit.VisualStudio.TestAdapter.Tests
[Test]
public void PropertyValueProviderCategoryWithOneCategory()
{
- CheckTraitsSupported();
-
var tc = new TestCase("Test1", new Uri("executor://NUnitTestExecutor"), "NUnit.VSIX");
tc.AddTrait("Category", "CI");
var testFilter = new TfsTestFilter(null);
@@ -57,8 +55,6 @@ namespace NUnit.VisualStudio.TestAdapter.Tests
[Test]
public void PropertyValueProviderCategoryWithNoTraits()
{
- CheckTraitsSupported();
-
var tc = new TestCase("Test1", new Uri("executor://NUnitTestExecutor"), "NUnit.VSIX");
var testFilter = new TfsTestFilter(null);
var obj = TfsTestFilter.PropertyValueProvider(tc, "TestCategory");
@@ -68,8 +64,6 @@ namespace NUnit.VisualStudio.TestAdapter.Tests
[Test]
public void PropertyValueProviderCategoryWithMultipleCategories()
{
- CheckTraitsSupported();
-
var tc = new TestCase("Test1", new Uri("executor://NUnitTestExecutor"), "NUnit.VSIX");
tc.AddTrait("Category", "CI");
tc.AddTrait("Category", "MyOwn");
@@ -90,11 +84,5 @@ namespace NUnit.VisualStudio.TestAdapter.Tests
var obj = TfsTestFilter.PropertyValueProvider(tc, "Garbage");
Assert.Null(obj);
}
-
- private static void CheckTraitsSupported()
- {
- if (!TraitsFeature.IsSupported)
- Assert.Inconclusive("This version of Visual Studio does not support Traits");
- }
}
}

Removed the check to verify if traits are supported by reflection method.
Thus this will not work with older object models.