I came across a situation where I needed to generate a TRX
file dynamically for a set of tests. This TRX would then to be used to rerun
the set of tests.
To create a utility for this, I needed 3 pre-requisites:
·
List of test names
·
A TRX file template with one test
·
VSMDI file which has the test case details
The TRX template looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<TestRun id="75ef9a27-b8ce-4c81-a2bb-fb3e26088e32" name="xxx" runUser="xxx" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
<TestSettings name="Local" id="3402c4f6-3b10-4472-9f2c-14a883c33075">
<Description>These
are default test settings for a local test run.</Description>
<Deployment enabled="false" runDeploymentRoot="anujc_ANUJDEV1 2012-10-09 17_43_06">
</Deployment>
<Execution hostProcessPlatform="MSIL">
<TestTypeSpecific>
<UnitTestRunConfig testTypeId="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b">
<AssemblyResolution applicationBaseDirectory="xxx ">
<TestDirectory useLoadContext="true" />
<RuntimeResolution>
<Directory path=" xxx " includeSubDirectories="true" />
</RuntimeResolution>
</AssemblyResolution>
</UnitTestRunConfig>
</TestTypeSpecific>
<AgentRule name="LocalMachineDefaultRole">
</AgentRule>
</Execution>
</TestSettings>
<Times creation="2012-10-09T17:43:06.8818053-07:00" queuing="2012-10-09T17:43:08.3979569-07:00" start="2012-10-09T17:43:08.5789750-07:00" finish="2012-10-09T18:01:43.5194579-07:00" />
<ResultSummary outcome="Failed">
<Counters total="1" executed="1" passed="0" error="0" failed="0" timeout="0" aborted="0" inconclusive="0" passedButRunAborted="0" notRunnable="0" notExecuted="0" disconnected="0" warning="0" completed="1" inProgress="0" pending="0" />
</ResultSummary>
<TestDefinitions>
<UnitTest name="DefaultTestName" storage=" xxx">
<Description>DefaultDescription</Description>
<Execution id="e58026f9-1eb9-4f96-8fc9-e672dce1e6c7" />
<Properties>
<Property>
<Key>JobID</Key>
<Value>133069</Value>
</Property>
</Properties>
<TestMethod codeBase=" xxx" adapterTypeName="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestAdapter,
Microsoft.VisualStudio.QualityTools.Tips.UnitTest.Adapter, Version=10.0.0.0,
Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" className=" xxx, Federation4.5,
Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" name="DefaultTestName" />
</UnitTest>
</TestDefinitions>
<TestLists>
<TestList name="All Loaded Results" id="19431567-8539-422a-85d7-44ee4e166bda" />
</TestLists>
<TestEntries>
<TestEntry testId="5099c33a-7e6b-4dff-8872-c0b6f614bbed" executionId="e58026f9-1eb9-4f96-8fc9-e672dce1e6c7" testListId="19431567-8539-422a-85d7-44ee4e166bda" />
</TestEntries>
<Results>
<UnitTestResult executionId="e58026f9-1eb9-4f96-8fc9-e672dce1e6c7" testId="5099c33a-7e6b-4dff-8872-c0b6f614bbed" testName="DefaultTestName" computerName=" xxx" duration="00:00:15.4887422" startTime="2012-10-09T17:43:08.7109882-07:00" endTime="2012-10-09T17:43:25.0076177-07:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Completed" testListId="19431567-8539-422a-85d7-44ee4e166bda" relativeResultsDirectory="e58026f9-1eb9-4f96-8fc9-e672dce1e6c7">
<Output>
<StdOut>Fake Log</StdOut>
</Output>
</UnitTestResult>
</Results>
</TestRun>
Now I created one method which reads the test properties
from the VSMDI
static string GetTestcaseIdFromVsmdi(string testcase)
{
XmlDocument
doc = new XmlDocument();
doc.Load(oldVsmdi);
XmlNamespaceManager
namespaceManager = new XmlNamespaceManager(new NameTable());
namespaceManager.AddNamespace("ns", "http://microsoft.com/schemas/VisualStudio/TeamTest/2010");
XmlNode
testLink = doc.SelectSingleNode("//ns:TestLink[@name='"
+ testcase + "']",
namespaceManager);
return
testLink.Attributes["id"].Value;
}
The below method creates a TRX for the list of test names
static void CreateNewTrx(List<string> selectedTests)
{
XmlDocument
doc = new XmlDocument();
doc.Load(oldTrx);
XmlNamespaceManager
namespaceManager = new XmlNamespaceManager(new NameTable());
namespaceManager.AddNamespace("ns", "http://microsoft.com/schemas/VisualStudio/TeamTest/2010");
XmlNode
unitTest = doc.SelectSingleNode("//ns:UnitTest",
namespaceManager);
XmlNode
testEntry = doc.SelectSingleNode("//ns:TestEntry",
namespaceManager);
XmlNode
unitTestResult = doc.SelectSingleNode("//ns:UnitTestResult",
namespaceManager);
XmlNode
counters = doc.SelectSingleNode("//ns:ResultSummary/ns:Counters",
namespaceManager);
counters.Attributes["total"].Value =
selectedTests.Count.ToString();
counters.Attributes["executed"].Value =
selectedTests.Count.ToString();
counters.Attributes["completed"].Value =
selectedTests.Count.ToString();
foreach
(string selectedTest in
selectedTests)
{
string
testId = GetTestcaseIdFromVsmdi(selectedTest);
string
executionId = Guid.NewGuid().ToString();
if
(doc.SelectSingleNode("//ns:UnitTest[@name='DefaultTestName']",
namespaceManager) != null)
{
unitTest.Attributes["name"].Value = selectedTest;
unitTest.Attributes["id"].Value = testId;
unitTest.SelectSingleNode("ns:Execution",
namespaceManager).Attributes["id"].Value
= executionId;
unitTest.SelectSingleNode("ns:TestMethod",
namespaceManager).Attributes["name"].Value
= selectedTest;
testEntry.Attributes["testId"].Value = testId;
testEntry.Attributes["executionId"].Value = executionId;
unitTestResult.Attributes["executionId"].Value = executionId;
unitTestResult.Attributes["testName"].Value = selectedTest;
unitTestResult.Attributes["testId"].Value = testId;
}
else
{
XmlNode
newUnitTest = unitTest.Clone();
newUnitTest.Attributes["name"].Value = selectedTest;
newUnitTest.Attributes["id"].Value = testId;
newUnitTest.SelectSingleNode("ns:Execution",
namespaceManager).Attributes["id"].Value
= executionId;
newUnitTest.SelectSingleNode("ns:TestMethod",
namespaceManager).Attributes["name"].Value
= selectedTest;
unitTest.ParentNode.AppendChild(newUnitTest);
XmlNode
newtestEntry = testEntry.Clone();
newtestEntry.Attributes["testId"].Value = testId;
newtestEntry.Attributes["executionId"].Value = executionId;
testEntry.ParentNode.AppendChild(newtestEntry);
XmlNode
newUnitTestResult = unitTestResult.Clone();
newUnitTestResult.Attributes["executionId"].Value
= executionId;
newUnitTestResult.Attributes["testName"].Value
= selectedTest;
newUnitTestResult.Attributes["testId"].Value
= testId;
unitTestResult.ParentNode.AppendChild(newUnitTestResult);
}
}
doc.Save(newTrx);
}
Now you are ready to run the tests from the TRX.
The only thing to note is that while running the tests from
the Test Results window, don’t check any test. Just click Run and Enjoy!