Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ internal abstract class TestElement : ITestElement, IXmlTestStore
protected TestExecId _parentExecutionId;
protected TestCategoryItemCollection _testCategories;
protected WorkItemCollection _workItems;
protected TestPropertyItemCollection _testProperties;
protected TestListCategoryId _catId;

public TestElement(Guid id, string name, string adapter)
Expand Down Expand Up @@ -178,6 +179,16 @@ public WorkItemCollection WorkItems
}
}

public TestPropertyItemCollection TestProperties
{
get { return _testProperties; }
set
{
EqtAssert.ParameterNotNull(value, "TestProperties");
_testProperties = value;
}
}

/// <summary>
/// Gets the adapter name.
/// </summary>
Expand Down Expand Up @@ -238,6 +249,7 @@ public virtual void Save(System.Xml.XmlElement element, XmlTestStoreParameters p
h.SaveSimpleField(element, "@priority", _priority, DefaultPriority);
h.SaveSimpleField(element, "Owners/Owner/@name", _owner, string.Empty);
h.SaveObject(_testCategories, element, "TestCategory", parameters);
h.SaveObject(_testProperties, element, "Properties", parameters);

if (_executionId != null)
h.SaveGuid(element, "Execution/@id", _executionId.Id);
Expand All @@ -262,6 +274,7 @@ private void Initialize()
_parentExecutionId = TestExecId.Empty;
_testCategories = new TestCategoryItemCollection();
_workItems = new WorkItemCollection();
_testProperties = new TestPropertyItemCollection();
_isRunnable = true;
_catId = TestListCategoryId.Uncategorized;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
// 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.TestPlatform.Extensions.TrxLogger.ObjectModel;

using System;
using System.Text;

using Utility;

using XML;

#region TestPropertyItem
/// <summary>
/// Stores a string which categorizes the Test
/// </summary>
internal sealed class TestPropertyItem : IXmlTestStore
{
#region Fields
[StoreXmlSimpleField(Location = "Key", DefaultValue = "")]
private readonly string _key = string.Empty;

[StoreXmlSimpleField(Location = "Value", DefaultValue = "")]
private readonly string _value = string.Empty;

#endregion

#region Constructors
/// <summary>
/// Create a new item with the key/value set
/// </summary>
/// <param name="key">The key.</param>
/// <param name="value">The value.</param>
public TestPropertyItem(string key, string value)
{
// Treat null as empty.
if (string.IsNullOrEmpty(key))
throw new ArgumentNullException(nameof(key));

if (value == null)
{
value = String.Empty;
}

_key = key;
_value = value;
}

#endregion

#region Properties/Methods
/// <summary>
/// Gets the Key for this TestProperty
/// </summary>
public string Key
{
get
{
return _key;
}
}

/// <summary>
/// Gets the Value for this TestProperty
/// </summary>
public string Value
{
get
{
return _value;
}
}

#endregion

#region Methods - overrides
/// <summary>
/// Compare the values of the items
/// </summary>
/// <param name="other">Value being compared to.</param>
/// <returns>True if the values are the same and false otherwise.</returns>
public override bool Equals(object other)
{
TestPropertyItem otherItem = other as TestPropertyItem;
if (otherItem == null)
{
return false;
}
return String.Equals(_key, otherItem._key, StringComparison.OrdinalIgnoreCase) && String.Equals(_value, otherItem._value, StringComparison.Ordinal);
}

/// <summary>
/// Convert the property name to a hashcode
/// </summary>
/// <returns>Hashcode of the category.</returns>
public override int GetHashCode()
{
return _key.ToUpperInvariant().GetHashCode() ^ _value.GetHashCode();
}

/// <summary>
/// Convert the property name to a string
/// </summary>
/// <returns>The property.</returns>
public override string ToString()
{
return _key + " = " + _value;
}
#endregion

#region IXmlTestStore Members

/// <summary>
/// Saves the class under the XmlElement.
/// </summary>
/// <param name="element"> XmlElement element </param>
/// <param name="parameters"> XmlTestStoreParameters parameters</param>
public void Save(System.Xml.XmlElement element, XmlTestStoreParameters parameters)
{
new XmlPersistence().SaveSingleFields(element, this, parameters);
}

#endregion
}
#endregion

#region TestPropertyItemCollection
/// <summary>
/// A collection of strings which categorize the test.
/// </summary>
internal sealed class TestPropertyItemCollection : EqtBaseCollection<TestPropertyItem>
{
#region Constructors
/// <summary>
/// Creates an empty TestPropertyItemCollection.
/// </summary>
public TestPropertyItemCollection()
{
_childElementName = "Property";
}

#endregion

#region Methods

/// <summary>
/// Adds the property.
/// </summary>
/// <param name="key">Key to be added.</param>
/// <param name="value">Value to be added.</param>
public void Add(string key, string value)
{
Add(new TestPropertyItem(key, value));
}

/// <summary>
/// Adds the property.
/// </summary>
/// <param name="item">Property to be added.</param>
public override void Add(TestPropertyItem item)
{
EqtAssert.ParameterNotNull(item, nameof(item));

// Don't add empty items.
if (!String.IsNullOrEmpty(item.Key))
{
base.Add(item);
}
}

/// <summary>
/// Convert the TestPropertyItemCollection to a string.
/// each item is surrounded by a comma (,)
/// </summary>
/// <returns></returns>
public override string ToString()
{
var returnString = new StringBuilder();
if (Count > 0)
{
returnString.Append(',');
foreach (TestPropertyItem item in this)
{
returnString.Append(item.ToString());
returnString.Append(',');
}
}

return returnString.ToString();
}

/// <summary>
/// Compare the collection items
/// </summary>
/// <param name="obj">other collection</param>
/// <returns>true if the collections contain the same items</returns>
public override bool Equals(object obj)
{
TestPropertyItemCollection other = obj as TestPropertyItemCollection;
bool result = false;

if (other == null)
{
// Other object is not a TestPropertyItemCollection.
result = false;
}
else if (Object.ReferenceEquals(this, other))
{
// The other object is the same object as this one.
result = true;
}
else if (Count != other.Count)
{
// The count of categories in the other object does not
// match this one, so they are not equal.
result = false;
}
else
{
// Check each item and return on the first mismatch.
foreach (TestPropertyItem item in this)
{
if (!other.Contains(item))
{
result = false;
break;
}
}
}

return result;
}

/// <summary>
/// Return the hash code of this collection
/// </summary>
/// <returns>The hashcode.</returns>
public override int GetHashCode()
{
return base.GetHashCode();
}
#endregion
}
#endregion
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public void Dispose()
#region Fields
protected Hashtable _container;

private string _childElementName;
protected string _childElementName;
#endregion

#region Constructors
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ public ITestElement ToTestElement(
testElement.WorkItems.Add(workItem);
}

foreach (var trait in rockSteadyTestCase.Traits)
{
testElement.TestProperties.Add(trait.Name, trait.Value);
}

return testElement;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,53 @@ public void TestRunInformationShouldContainUtcDateTime()
ValidateDateTimeInTrx(_testableTrxLogger.TrxFile);
}

[TestMethod]
public void TraitsForTestCaseShouldBeOutputtedInTrx()
{
ObjectModel.TestCase testCase = CreateTestCase("TestCaseWithTraits");
testCase.Traits.Add("Trait1", "Value1");
testCase.Traits.Add("Trait2", "Value2");

var result = new ObjectModel.TestResult(testCase);
var resultEventArg1 = new Mock<TestResultEventArgs>(result);

_testableTrxLogger.TestResultHandler(new object(), resultEventArg1.Object);

var testRunCompleteEventArgs = TrxLoggerTests.CreateTestRunCompleteEventArgs();
_testableTrxLogger.TestRunCompleteHandler(new object(), testRunCompleteEventArgs);

Assert.IsTrue(File.Exists(_testableTrxLogger.TrxFile), string.Format("TRX file: {0}, should have got created.", _testableTrxLogger.TrxFile));

// Validate TRX output - we expect something like this:
/*
<Properties>
<Property>
<Key>Trait1</Key>
<Value>Value1</Value>
</Property>
<Property>
<Key>Trait2</Key>
<Value>Value2</Value>
</Property>
</Properties>
*/

using FileStream file = File.OpenRead(_testableTrxLogger.TrxFile);
using XmlReader reader = XmlReader.Create(file);
XDocument document = XDocument.Load(reader);
XNamespace ns = document.Root.GetDefaultNamespace();
var testDefinitionsElement = document.Descendants(ns.GetName("TestDefinitions")).FirstOrDefault();
var unitTestElement = testDefinitionsElement.Element(ns.GetName("UnitTest"));

Assert.IsNotNull(unitTestElement, "Unable to find UnitTest element in TRX");

var propertiesElement = unitTestElement.Element(ns.GetName("Properties"));
Assert.IsNotNull(propertiesElement, "Unable to find Properties element for UnitTest element in TRX");

var propertyElements = propertiesElement.Elements(ns.GetName("Property"));
Assert.AreEqual(2, propertyElements.Count(), "We should have two properties logged in TRX");
}

private void ValidateDateTimeInTrx(string trxFileName)
{
using FileStream file = File.OpenRead(trxFileName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,24 @@ public void ToTestElementShouldAssignWorkItemOfUnitTestElement()
CollectionAssert.AreEquivalent(expected, unitTestElement.WorkItems.ToArray());
}

[TestMethod]
public void ToTestElementShouldShouldAssignTraitsOfUnitTestElement()
{
var testCase = CreateTestCase("TestCaseWithTraits");
var result = new TestPlatformObjectModel.TestResult(testCase);

testCase.Traits.Add("Trait1", "Value1");
testCase.Traits.Add("Trait2", "Value2");

var unitTestElement = _converter.ToTestElement(testCase.Id, Guid.Empty, Guid.Empty, testCase.DisplayName, TrxLoggerConstants.UnitTestType, testCase);

// They only way to check for TestProperties is to cast the ITestElement object to UnitTestElement
Assert.IsInstanceOfType(unitTestElement, typeof(UnitTestElement));

var expected = new[] { new TestPropertyItem("Trait1", "Value1"), new TestPropertyItem("Trait2", "Value2") };
CollectionAssert.AreEquivalent(expected, ((UnitTestElement)unitTestElement).TestProperties.ToArray());
}

/// <summary>
/// Unit test for regression when there's no test categories.
/// </summary>
Expand Down