diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/ITestElement.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/ITestElement.cs index 92d7db22f4..39121ae3e0 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/ITestElement.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/ITestElement.cs @@ -16,6 +16,7 @@ internal interface ITestElement TestExecId ParentExecutionId { get; set; } TestListCategoryId CategoryId { get; set; } TestCategoryItemCollection TestCategories { get; } + WorkItemCollection WorkItems { get; set; } TestType TestType { get; } } } diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestElement.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestElement.cs index 9562822962..c35fa8b3a1 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestElement.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestElement.cs @@ -30,6 +30,7 @@ internal abstract class TestElement : ITestElement, IXmlTestStore protected TestExecId executionId; protected TestExecId parentExecutionId; protected TestCategoryItemCollection testCategories; + protected WorkItemCollection workItems; protected TestListCategoryId catId; public TestElement(Guid id, string name, string adapter) @@ -161,6 +162,20 @@ public TestCategoryItemCollection TestCategories } } + /// + /// Gets or sets the work items. + /// + public WorkItemCollection WorkItems + { + get { return this.workItems; } + + set + { + EqtAssert.ParameterNotNull(value, "value"); + this.workItems = value; + } + } + /// /// Gets the adapter name. /// @@ -230,6 +245,8 @@ public virtual void Save(System.Xml.XmlElement element, XmlTestStoreParameters p if (this.parentExecutionId != null) h.SaveGuid(element, "Execution/@parentId", this.parentExecutionId.Id); + h.SaveObject(this.workItems, element, "Workitems", parameters); + XmlTestStoreParameters testIdParameters = XmlTestStoreParameters.GetParameters(); testIdParameters[TestId.IdLocationKey] = "@id"; h.SaveObject(this.id, element, testIdParameters); @@ -245,6 +262,7 @@ private void Initialize() this.executionId = TestExecId.Empty; this.parentExecutionId = TestExecId.Empty; this.testCategories = new TestCategoryItemCollection(); + this.workItems = new WorkItemCollection(); this.isRunnable = true; this.catId = TestListCategoryId.Uncategorized; } diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/WorkItems.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/WorkItems.cs new file mode 100644 index 0000000000..c21769539d --- /dev/null +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/WorkItems.cs @@ -0,0 +1,243 @@ +// 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.Globalization; + using System.Text; + using System.Xml; + using Microsoft.TestPlatform.Extensions.TrxLogger.Utility; + using Microsoft.TestPlatform.Extensions.TrxLogger.XML; + + #region WorkItem + /// + /// Stores an int which represents a workitem + /// + internal sealed class WorkItem : IXmlTestStore + { + #region Fields + [StoreXmlField(Location = ".")] + private int id = 0; + + #endregion + + #region Constructors + /// + /// Create a new item with the workitem set + /// + /// The workitem. + public WorkItem(int workitemId) + { + this.id = workitemId; + } + + #endregion + + #region Properties/Methods + /// + /// Gets the id for this WorkItem + /// + public int Id + { + get + { + return this.id; + } + } + + #endregion + + #region Methods - overrides + /// + /// Compare the values of the items + /// + /// Value being compared to. + /// True if the values are the same and false otherwise. + public override bool Equals(object other) + { + WorkItem otherItem = other as WorkItem; + if (otherItem == null) + { + return false; + } + return this.id == otherItem.id; + } + + /// + /// Convert the workitem to a hashcode + /// + /// Hashcode of the workitem. + public override int GetHashCode() + { + return this.id.GetHashCode(); + } + + /// + /// Convert the workitem to a string + /// + /// The workitem. + public override string ToString() + { + return this.id.ToString(CultureInfo.InvariantCulture); + } + #endregion + + #region IXmlTestStore Members + + /// + /// Saves the class under the XmlElement. + /// + /// XmlElement element + /// XmlTestStoreParameters parameters + public void Save(System.Xml.XmlElement element, XmlTestStoreParameters parameters) + { + new XmlPersistence().SaveSingleFields(element, this, parameters); + } + + #endregion + } + #endregion + + #region WorkItemCollection + /// + /// A collection of ints represent the workitems + /// + internal sealed class WorkItemCollection : EqtBaseCollection + { + #region Constructors + /// + /// Creates an empty WorkItemCollection. + /// + public WorkItemCollection() + { + } + + /// + /// Create a new WorkItemCollection based on the int array. + /// + /// Add these items to the collection. + public WorkItemCollection(int[] items) + { + EqtAssert.ParameterNotNull(items, "items"); + foreach (int i in items) + { + this.Add(new WorkItem(i)); + } + } + + #endregion + + #region Methods + /// + /// Adds the workitem. + /// + /// WorkItem to be added. + public void Add(int item) + { + this.Add(new WorkItem(item)); + } + + /// + /// Adds the workitem. + /// + /// WorkItem to be added. + public override void Add(WorkItem item) + { + EqtAssert.ParameterNotNull(item, "item"); + base.Add(item); + } + + /// + /// Convert the WorkItemCollection to a string. + /// each item is separated by a comma (,) + /// + /// + public override string ToString() + { + StringBuilder returnString = new StringBuilder(); + if (this.Count > 0) + { + returnString.Append(","); + foreach (WorkItem item in this) + { + returnString.Append(item); + returnString.Append(","); + } + } + + return returnString.ToString(); + } + + /// + /// Convert the WorkItemCollection to an array of ints. + /// + /// Array of ints containing the workitems. + public int[] ToArray() + { + int[] result = new int[this.Count]; + + int i = 0; + foreach (WorkItem item in this) + { + result[i++] = item.Id; + } + + return result; + } + + /// + /// Compare the collection items + /// + /// other collection + /// true if the collections contain the same items + public override bool Equals(object obj) + { + WorkItemCollection other = obj as WorkItemCollection; + bool result = false; + + if (other == null) + { + result = false; + } + else if (object.ReferenceEquals(this, other)) + { + result = true; + } + else if (this.Count != other.Count) + { + result = false; + } + else + { + foreach (WorkItem item in this) + { + if (!other.Contains(item)) + { + result = false; + break; + } + } + } + + return result; + } + + /// + /// Return the hash code of this collection + /// + /// The hashcode. + public override int GetHashCode() + { + return base.GetHashCode(); + } + + public override void Save(XmlElement element, XmlTestStoreParameters parameters) + { + XmlPersistence xmlPersistence = new XmlPersistence(); + xmlPersistence.SaveHashtable(this.container, element, ".", ".", null, "Workitem", parameters); + } + #endregion + } + #endregion +} diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Utility/Converter.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Utility/Converter.cs index 3ca84b4694..eeb441f0d4 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Utility/Converter.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Utility/Converter.cs @@ -67,6 +67,13 @@ public ITestElement ToTestElement( testElement.TestCategories.Add(testCategory); } + var workItems = GetCustomPropertyValueFromTestCase(rockSteadyTestCase, "WorkItemIds") + .Select(workItem => int.Parse(workItem)); + foreach (int workItem in workItems) + { + testElement.WorkItems.Add(workItem); + } + return testElement; } diff --git a/test/Microsoft.TestPlatform.Extensions.TrxLogger.UnitTests/TrxLoggerTests.cs b/test/Microsoft.TestPlatform.Extensions.TrxLogger.UnitTests/TrxLoggerTests.cs index c55c000053..67dd775c4a 100644 --- a/test/Microsoft.TestPlatform.Extensions.TrxLogger.UnitTests/TrxLoggerTests.cs +++ b/test/Microsoft.TestPlatform.Extensions.TrxLogger.UnitTests/TrxLoggerTests.cs @@ -736,13 +736,11 @@ public void CustomTrxFileNameShouldConstructFromLogFileParameter() Assert.AreEqual(Path.Combine(TrxLoggerTests.DefaultTestRunDirectory, TrxLoggerTests.DefaultLogFileNameParameterValue), this.testableTrxLogger.trxFile, "Wrong Trx file name"); } - - /// /// Unit test for reading TestCategories from the TestCase which is part of test result. /// [TestMethod] - public void GetCustomPropertyValueFromTestCaseShouldReadCategoyrAttributesFromTestCase() + public void GetCustomPropertyValueFromTestCaseShouldReadCategoryAttributesFromTestCase() { ObjectModel.TestCase testCase1 = CreateTestCase("TestCase1"); TestProperty testProperty = TestProperty.Register("MSTestDiscoverer.TestCategory", "String array property", string.Empty, string.Empty, typeof(string[]), null, TestPropertyAttributes.Hidden, typeof(TestObject)); @@ -759,6 +757,24 @@ public void GetCustomPropertyValueFromTestCaseShouldReadCategoyrAttributesFromTe CollectionAssert.AreEqual(listCategoriesExpected, listCategoriesActual); } + [TestMethod] + public void GetCustomPropertyValueFromTestCaseShouldReadWorkItemAttributesFromTestCase() + { + ObjectModel.TestCase testCase1 = CreateTestCase("TestCase1"); + TestProperty testProperty = TestProperty.Register("WorkItemIds", "String array property", string.Empty, string.Empty, typeof(string[]), null, TestPropertyAttributes.Hidden, typeof(TestObject)); + + testCase1.SetPropertyValue(testProperty, new[] { "99999", "0" }); + + var converter = new Converter(new Mock().Object, new TrxFileHelper()); + List listWorkItemsActual = converter.GetCustomPropertyValueFromTestCase(testCase1, "WorkItemIds"); + + List listWorkItemsExpected = new List(); + listWorkItemsExpected.Add("99999"); + listWorkItemsExpected.Add("0"); + + CollectionAssert.AreEqual(listWorkItemsExpected, listWorkItemsActual); + } + [TestMethod] public void CRLFCharactersShouldGetRetainedInTrx() { diff --git a/test/Microsoft.TestPlatform.Extensions.TrxLogger.UnitTests/Utility/ConverterTests.cs b/test/Microsoft.TestPlatform.Extensions.TrxLogger.UnitTests/Utility/ConverterTests.cs index 6311ba1715..e4c2323f83 100644 --- a/test/Microsoft.TestPlatform.Extensions.TrxLogger.UnitTests/Utility/ConverterTests.cs +++ b/test/Microsoft.TestPlatform.Extensions.TrxLogger.UnitTests/Utility/ConverterTests.cs @@ -98,6 +98,22 @@ public void ToTestElementShouldAssignTestCategoryOfUnitTestElement() CollectionAssert.AreEqual(expected, unitTestElement.TestCategories.ToArray().OrderByDescending(x => x.ToString()).ToArray()); } + [TestMethod] + public void ToTestElementShouldAssignWorkitemOfUnitTestElement() + { + TestPlatformObjectModel.TestCase testCase = CreateTestCase("TestCase1"); + TestPlatformObjectModel.TestResult result = new TestPlatformObjectModel.TestResult(testCase); + TestProperty testProperty = TestProperty.Register("WorkItemIds", "String array property", string.Empty, string.Empty, typeof(string[]), null, TestPropertyAttributes.Hidden, typeof(TestObject)); + + testCase.SetPropertyValue(testProperty, new[] { "3", "99999", "0" }); + + var unitTestElement = this.converter.ToTestElement(testCase.Id, Guid.Empty, Guid.Empty, testCase.DisplayName, TrxLoggerConstants.UnitTestType, testCase); + + int[] expected = new[] { 0, 3, 99999 }; + + CollectionAssert.AreEquivalent(expected, unitTestElement.WorkItems.ToArray()); + } + /// /// Unit test for regression when there's no test categories. ///