Adding Traits cache instead of recursion.
Removed recursion in AddTraitsFromTestNode method.
Cached the class and assembly level traits so that we don't need to traverse the tree again.
Reading test-case, test-suite and assembly level attributes based on the tree structure.
MODIFY
src/NUnitTestAdapter/NUnit3TestDiscoverer.cs
src/NUnitTestAdapter/NUnit3TestDiscoverer.cs
@@ -158,7 +158,7 @@ namespace NUnit.VisualStudio.TestAdapter
private int ProcessTestCases(XmlNode topNode, ITestCaseDiscoverySink discoverySink, TestConverter testConverter)
{
int cases = 0;
-
+ testConverter.BuildAttributesCache(topNode);
foreach (XmlNode testNode in topNode.SelectNodes("//test-case"))
{
try

MODIFY
src/NUnitTestAdapter/TestConverter.cs
src/NUnitTestAdapter/TestConverter.cs
@@ -39,6 +39,7 @@ namespace NUnit.VisualStudio.TestAdapter
private readonly string _sourceAssembly;
private NavigationDataProvider _navigationDataProvider;
private bool _collectSourceInformation;
+ private IDictionary<string, List<KeyValuePair<string, string>>> _attributesCache;
#region Constructor
@@ -118,10 +119,60 @@ namespace NUnit.VisualStudio.TestAdapter
return results;
}
+ /// <summary>
+ /// Builds attributes cache for the testrun / assembly
+ /// </summary>
+ /// <param name="topNode"></param>
+ public void BuildAttributesCache(XmlNode topNode)
+ {
+ var assemblyAttributes = topNode.SelectNodes("properties/property");
+ this.ReadAttributes(assemblyAttributes);
+
+ var testSuiteAttributes = topNode.SelectNodes("test-suite/test-suite/properties/property");
+ this.ReadAttributes(testSuiteAttributes);
+
+ var testCaseAttributes = topNode.SelectNodes("test-suite/test-suite/test-case/properties/property");
+ this.ReadAttributes(testCaseAttributes);
+
+ }
+
#endregion
#region Helper Methods
+ private void ReadAttributes(XmlNodeList attributes)
+ {
+ var enumerator = attributes.GetEnumerator();
+
+ while(enumerator.MoveNext())
+ {
+ var property = (XmlNode)enumerator.Current;
+ var parentId = property.ParentNode?.ParentNode?.Attributes["id"]?.Value ?? "0-0000";
+
+ var propertyName = property.Attributes["name"]?.Value;
+ var propertyValue = property.Attributes["value"]?.Value;
+
+ this.AddAttributesToCache(parentId, propertyName, propertyValue);
+ }
+ }
+
+ private void AddAttributesToCache(string parentId, string propertyName, string propertyValue)
+ {
+ if (!string.IsNullOrEmpty(propertyName) && propertyName[0] != '_' && !string.IsNullOrEmpty(propertyValue))
+ {
+ if (_attributesCache.ContainsKey(parentId))
+ {
+ _attributesCache[parentId].Add(new KeyValuePair<string, string>(propertyName, propertyValue));
+ }
+ else
+ {
+ var kps = new List<KeyValuePair<string, string>>();
+ kps.Add(new KeyValuePair<string, string>(propertyName, propertyValue));
+ _attributesCache[parentId] = kps;
+ }
+ }
+ }
+
/// <summary>
/// Makes a TestCase from an NUnit test, adding
/// navigation data if it can be found.
@@ -150,7 +201,7 @@ namespace NUnit.VisualStudio.TestAdapter
}
}
- testCase.AddTraitsFromTestNode(testNode);
+ testCase.AddTraitsFromTestNode(testNode, this._attributesCache);
return testCase;
}

MODIFY
src/NUnitTestAdapter/TraitsFeature.cs
src/NUnitTestAdapter/TraitsFeature.cs
@@ -68,10 +68,33 @@ namespace NUnit.VisualStudio.TestAdapter
}
}
- public static void AddTraitsFromTestNode(this TestCase testCase, XmlNode testNode)
+ public static void AddTraitsFromTestNode(this TestCase testCase, XmlNode testNode, IDictionary<string,List<KeyValuePair<string,string>>> propertiesCache)
{
if (IsSupported)
- AddTraitsFromTestNode(testNode, TraitsProperty.GetValue(testCase, new object[0]));
+ {
+ var assemblyId = testNode.ParentNode?.ParentNode?.Attributes["id"]?.Value;
+ List<KeyValuePair<string, string>> testCaseProperties = new List<KeyValuePair<string, string>>();
+
+ // Reading properties at the assembly level.
+ if(!string.IsNullOrEmpty(assemblyId) && propertiesCache.ContainsKey(assemblyId))
+ testCaseProperties = propertiesCache[assemblyId];
+
+ // Reading properties at the class (test suite) level.
+ var testSuiteId = testNode.ParentNode?.Attributes["id"]?.Value;
+ if(!string.IsNullOrEmpty(testSuiteId) && propertiesCache.ContainsKey(testSuiteId))
+ testCaseProperties.AddRange(propertiesCache[testSuiteId]);
+
+ // Reading properties at the test case level.
+ var testCaseId = testNode?.Attributes["id"].Value;
+ if(!string.IsNullOrEmpty(testCaseId) && propertiesCache.ContainsKey(testCaseId))
+ testCaseProperties.AddRange(propertiesCache[testCaseId]);
+
+ var obj = TraitsProperty.GetValue(testCase, new object[0]);
+ foreach (var property in testCaseProperties)
+ {
+ TraitsCollectionAdd.Invoke(obj, new object[] { property.Key, property.Value });
+ }
+ }
}
private static void AddTraitsFromTestNode(XmlNode test, object traitsCollection)

Adding Traits cache instead of recursion.

- Removed recursion in AddTraitsFromTestNode method.
- Cached the class and assembly level traits so that we don't need to traverse the tree again.
- Reading test-case, test-suite and assembly level attributes based on the tree structure.