Skip to content

Commit fa4e09f

Browse files
authored
Write props of tests into trx (#14905)
* props * fixes
1 parent daec8d1 commit fa4e09f

File tree

7 files changed

+263
-13
lines changed

7 files changed

+263
-13
lines changed

src/Microsoft.TestPlatform.CoreUtilities/FeatureFlag/FeatureFlag.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ private FeatureFlag() { }
7272
// Disable not sharing .NET Framework testhosts. Which will return behavior to sharing testhosts when they are running .NET Framework dlls, and are not disabling appdomains or running in parallel.
7373
public const string VSTEST_DISABLE_SHARING_NETFRAMEWORK_TESTHOST = nameof(VSTEST_DISABLE_SHARING_NETFRAMEWORK_TESTHOST);
7474

75+
// Disable outputting Traits into TRX file in the Properties node.
76+
public const string VSTEST_DISABLE_TRX_WRITE_PROPERTIES = nameof(VSTEST_DISABLE_TRX_WRITE_PROPERTIES);
7577

7678
[Obsolete("Only use this in tests.")]
7779
internal static void Reset()

src/Microsoft.TestPlatform.CoreUtilities/Properties/AssemblyInfo.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Runtime.CompilerServices;
55

66
[assembly: InternalsVisibleTo("Microsoft.TestPlatform.TestHostRuntimeProvider, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")]
7+
[assembly: InternalsVisibleTo("Microsoft.VisualStudio.TestPlatform.Extensions.Trx.TestLogger, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")]
78
[assembly: InternalsVisibleTo("vstest.console, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")]
89
[assembly: InternalsVisibleTo("vstest.console.arm64, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")]
910
[assembly: InternalsVisibleTo("Microsoft.TestPlatform.CoreUtilities.UnitTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")]

src/Microsoft.TestPlatform.Extensions.TrxLogger/Microsoft.TestPlatform.Extensions.TrxLogger.csproj

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232

3333
<ItemGroup>
3434
<Compile Include="$(RepoRoot)src\Microsoft.TestPlatform.TestHostProvider\Properties\TestExtensionTypesAttribute.cs" Link="Properties\TestExtensionTypesAttribute.cs" />
35-
<Compile Include="..\..\shared\NullableAttributes.cs" Link="NullableAttributes.cs" />
3635
</ItemGroup>
3736

3837
<ItemGroup>
@@ -49,11 +48,6 @@
4948
</ItemGroup>
5049

5150
<ItemGroup>
52-
<Compile Update="NullableHelpers.cs">
53-
<DesignTime>True</DesignTime>
54-
<AutoGen>True</AutoGen>
55-
<DependentUpon>NullableHelpers.tt</DependentUpon>
56-
</Compile>
5751
<Compile Update="Resources\TrxResource.Designer.cs">
5852
<DesignTime>True</DesignTime>
5953
<AutoGen>True</AutoGen>
@@ -81,13 +75,6 @@
8175
<AdditionalFiles Include="PublicAPI/$(TargetFramework)/PublicAPI.Unshipped.txt" />
8276
</ItemGroup>
8377

84-
<ItemGroup>
85-
<None Update="NullableHelpers.tt">
86-
<Generator>TextTemplatingFileGenerator</Generator>
87-
<LastGenOutput>NullableHelpers.cs</LastGenOutput>
88-
</None>
89-
</ItemGroup>
90-
9178
<ItemGroup>
9279
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
9380
</ItemGroup>
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
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+
using System;
5+
6+
using Microsoft.TestPlatform.Extensions.TrxLogger.XML;
7+
using Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger;
8+
9+
namespace Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel;
10+
11+
/// <summary>
12+
/// Stores a string which categorizes the Test
13+
/// </summary>
14+
internal sealed class Property : IXmlTestStore
15+
{
16+
[StoreXmlSimpleField(Location = "@Key", DefaultValue = "")]
17+
private readonly string _key = string.Empty;
18+
[StoreXmlSimpleField(Location = "@Value", DefaultValue = "")]
19+
private readonly string _value = string.Empty;
20+
21+
/// <summary>
22+
/// Create a new item with the property set
23+
/// </summary>
24+
public Property(string key, string value)
25+
{
26+
// Treat null as empty.
27+
28+
_key = StripIllegalChars(key);
29+
_value = StripIllegalChars(value);
30+
}
31+
32+
/// <summary>
33+
/// Gets the property for this Trait
34+
/// </summary>
35+
public string Trait
36+
{
37+
get
38+
{
39+
return _key;
40+
}
41+
}
42+
43+
private static string StripIllegalChars(string property)
44+
{
45+
string ret = property.Trim();
46+
ret = ret.Replace("&", string.Empty);
47+
ret = ret.Replace("|", string.Empty);
48+
ret = ret.Replace("!", string.Empty);
49+
ret = ret.Replace(",", string.Empty);
50+
return ret;
51+
}
52+
53+
/// <summary>
54+
/// Compare the values of the items
55+
/// </summary>
56+
/// <param name="other">Value being compared to.</param>
57+
/// <returns>True if the values are the same and false otherwise.</returns>
58+
public override bool Equals(object? other)
59+
{
60+
if (other is not Property otherItem)
61+
{
62+
return false;
63+
}
64+
65+
TPDebug.Assert(_key != null, "property is null");
66+
return string.Equals(_key, otherItem._key, StringComparison.OrdinalIgnoreCase);
67+
}
68+
69+
/// <summary>
70+
/// Convert the property name to a hashcode
71+
/// </summary>
72+
/// <returns>Hashcode of the property.</returns>
73+
public override int GetHashCode()
74+
{
75+
TPDebug.Assert(_key != null, "property is null");
76+
return _key.ToUpperInvariant().GetHashCode();
77+
}
78+
79+
/// <summary>
80+
/// Convert the property name to a string
81+
/// </summary>
82+
/// <returns>The property.</returns>
83+
public override string ToString()
84+
{
85+
TPDebug.Assert(_key != null, "property is null");
86+
return _key;
87+
}
88+
89+
/// <summary>
90+
/// Saves the class under the XmlElement.
91+
/// </summary>
92+
/// <param name="element"> XmlElement element </param>
93+
/// <param name="parameters"> XmlTestStoreParameters parameters</param>
94+
public void Save(System.Xml.XmlElement element, XmlTestStoreParameters? parameters)
95+
{
96+
new XmlPersistence().SaveSingleFields(element, this, parameters);
97+
}
98+
}
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
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+
using System.Text;
5+
6+
using Microsoft.TestPlatform.Extensions.TrxLogger.Utility;
7+
using Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger;
8+
9+
namespace Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel;
10+
11+
/// <summary>
12+
/// A collection of strings which categorize the test.
13+
/// </summary>
14+
internal sealed class PropertyCollection : EqtBaseCollection<Property>
15+
{
16+
/// <summary>
17+
/// Creates an empty PropertyCollection.
18+
/// </summary>
19+
public PropertyCollection()
20+
{
21+
}
22+
23+
/// <summary>
24+
/// Adds the property.
25+
/// </summary>
26+
/// <param name="key">Key to be added.</param>
27+
/// <param name="value">Value to be added.</param>
28+
public void Add(string key, string value)
29+
{
30+
Add(new Property(key, value));
31+
}
32+
33+
/// <summary>
34+
/// Adds the property.
35+
/// </summary>
36+
/// <param name="item">Property to be added.</param>
37+
public override void Add(Property item)
38+
{
39+
EqtAssert.ParameterNotNull(item, nameof(item));
40+
41+
// Don't add empty items.
42+
if (!item.Trait.IsNullOrEmpty())
43+
{
44+
base.Add(item);
45+
}
46+
}
47+
48+
/// <summary>
49+
/// Convert the PropertyCollection to a string.
50+
/// each item is surrounded by a comma (,)
51+
/// </summary>
52+
/// <returns></returns>
53+
public override string ToString()
54+
{
55+
StringBuilder returnString = new();
56+
if (Count > 0)
57+
{
58+
returnString.Append(',');
59+
foreach (Property item in this)
60+
{
61+
returnString.Append(item.Trait);
62+
returnString.Append(',');
63+
}
64+
}
65+
66+
return returnString.ToString();
67+
}
68+
69+
/// <summary>
70+
/// Convert the PropertyCollection to an array of strings.
71+
/// </summary>
72+
/// <returns>Array of strings containing the test categories.</returns>
73+
public string[] ToArray()
74+
{
75+
string[] result = new string[Count];
76+
77+
int i = 0;
78+
foreach (Property item in this)
79+
{
80+
result[i++] = item.Trait;
81+
}
82+
83+
return result;
84+
}
85+
86+
/// <summary>
87+
/// Compare the collection items
88+
/// </summary>
89+
/// <param name="obj">other collection</param>
90+
/// <returns>true if the collections contain the same items</returns>
91+
public override bool Equals(object? obj)
92+
{
93+
bool result = false;
94+
95+
if (obj is not PropertyCollection other)
96+
{
97+
// Other object is not a TraitItemCollection.
98+
result = false;
99+
}
100+
else if (ReferenceEquals(this, other))
101+
{
102+
// The other object is the same object as this one.
103+
result = true;
104+
}
105+
else if (Count != other.Count)
106+
{
107+
// The count of categories in the other object does not
108+
// match this one, so they are not equal.
109+
result = false;
110+
}
111+
else
112+
{
113+
// Check each item and return on the first mismatch.
114+
foreach (Property item in this)
115+
{
116+
if (!other.Contains(item))
117+
{
118+
result = false;
119+
break;
120+
}
121+
}
122+
}
123+
124+
return result;
125+
}
126+
127+
/// <summary>
128+
/// Return the hash code of this collection
129+
/// </summary>
130+
/// <returns>The hashcode.</returns>
131+
public override int GetHashCode()
132+
{
133+
return base.GetHashCode();
134+
}
135+
}

src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestElement.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ internal abstract class TestElement : ITestElement, IXmlTestStore
3232
protected TestExecId _executionId;
3333
protected TestExecId _parentExecutionId;
3434
protected TestCategoryItemCollection _testCategories;
35+
protected PropertyCollection _properties;
3536
protected WorkItemCollection _workItems;
3637
protected TestListCategoryId _catId;
3738

@@ -46,6 +47,7 @@ public TestElement(Guid id, string name, string adapter)
4647
_executionId = TestExecId.Empty;
4748
_parentExecutionId = TestExecId.Empty;
4849
_testCategories = new TestCategoryItemCollection();
50+
_properties = new PropertyCollection();
4951
_workItems = new WorkItemCollection();
5052
_isRunnable = true;
5153
_catId = TestListCategoryId.Uncategorized;
@@ -185,6 +187,21 @@ public WorkItemCollection WorkItems
185187
}
186188
}
187189

190+
191+
/// <summary>
192+
/// Gets or sets the test traits.
193+
/// </summary>
194+
public PropertyCollection Traits
195+
{
196+
get { return _properties; }
197+
198+
set
199+
{
200+
EqtAssert.ParameterNotNull(value, "value");
201+
_properties = value;
202+
}
203+
}
204+
188205
/// <summary>
189206
/// Gets the adapter name.
190207
/// </summary>
@@ -245,6 +262,7 @@ public virtual void Save(System.Xml.XmlElement element, XmlTestStoreParameters?
245262
h.SaveSimpleField(element, "@priority", _priority, DefaultPriority);
246263
h.SaveSimpleField(element, "Owners/Owner/@name", _owner, string.Empty);
247264
h.SaveObject(_testCategories, element, "TestCategory", parameters);
265+
h.SaveObject(_properties, element, "Properties", parameters);
248266

249267
if (_executionId != null)
250268
h.SaveGuid(element, "Execution/@id", _executionId.Id);

src/Microsoft.TestPlatform.Extensions.TrxLogger/Utility/Converter.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
using Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger;
1515
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
1616
using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces;
17+
using Microsoft.VisualStudio.TestPlatform.Utilities;
1718

1819
using TrxLoggerResources = Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger.Resources.TrxResource;
1920
using TrxObjectModel = Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel;
@@ -76,6 +77,14 @@ public static ITestElement ToTestElement(
7677
testElement.WorkItems.Add(workItem);
7778
}
7879

80+
if (!FeatureFlag.Instance.IsSet(nameof(FeatureFlag.VSTEST_DISABLE_TRX_WRITE_PROPERTIES)))
81+
{
82+
foreach (var trait in rockSteadyTestCase.Traits.Where(t => t.Name is not "Owner" and not "Priority"))
83+
{
84+
testElement.Traits.Add(new Property(trait.Name, trait.Value));
85+
}
86+
}
87+
7988
return testElement;
8089
}
8190

0 commit comments

Comments
 (0)