I'm having trouble using XElement to parse multiple elements through an XUnit XML file and return the value.
Here is the XML File
<assemblies timestamp="07/31/2018 14:58:48">
<assembly name="C:\Users\bf\Documents\Visual Studio 2015\Projects\xUnitDemo\xUnitDemo\bin\Debug\xUnitDemo.DLL" environment="64-bit .NET 4.0.30319.42000 [collection-per-class, parallel (1 threads)]" test-framework="xUnit.net 2.3.1.3858" run-date="2018-07-31" run-time="14:58:47" config-file="C:\Users\bf\Documents\Visual Studio 2015\Projects\xUnitDemo\packages\xunit.runner.console.2.4.0\tools\net452\xunit.console.exe.Config" total="15" passed="14" failed="1" skipped="0" time="0.257" errors="0">
<errors />
<collection total="2" passed="1" failed="1" skipped="0" name="Test collection for xUnitDemo.SimpleTests" time="0.070">
<test name="xUnitDemo.SimpleTests.PassingTest" type="xUnitDemo.SimpleTests" method="PassingTest" time="0.0636741" result="Pass">
<traits>
<trait name="test" value="test" />
<trait name="requirement" value="test" />
<trait name="labels" value="test" />
</traits>
</test>
<test name="xUnitDemo.SimpleTests.FailingTest" type="xUnitDemo.SimpleTests" method="FailingTest" time="0.0059474" result="Fail">
<failure exception-type="Xunit.Sdk.EqualException">
<message><![CDATA[Assert.Equal() Failure\r\nExpected: 5\r\nActual: 4]]></message>
<stack-trace><![CDATA[ at xUnitDemo.SimpleTests.FailingTest() in C:\Users\smsf\documents\visual studio 2015\Projects\xUnitDemo\xUnitDemo\SimpleTests.cs:line 30]]></stack-trace>
</failure>
</test>
</collection>
</assembly>
</assemblies>
I'm able to parse through test element using this code.
private static List<TestResults> GetTestAutomationExecutionResult(string filePath)
{
List<TestResults> testResults = new List<TestResults>();
XElement xelement = XElement.Load(filePath);
IEnumerable<XElement> results = xelement.Elements().Where(e => e.Name.LocalName == "test");
foreach (var result in results)
{
if (result.Attribute("result").Value == "Fail")
{
testResults.Add(new TestResults(result.Attribute("result").Value, "this is where the failure message would go"));
}
else
{
testResults.Add(new TestResults(result.Attribute("result").Value, ""));
}
}
But I'm having a hard time trying to find and add message inside of failure element in the foreach.
result.Attribute("message").Value
CodePudding user response:
Your code has a couple problems:
The
<result>
elements are not direct children of the root element, soxelement.Elements().Where(e => e.Name.LocalName == "test")
does not select anything. You need to descend deeper into the hierarchy, e.g. withDescendants()
.The message text is contained in an indirect child element of the
<test>
node, specificallyfailure/message
. You need to select this element to get the message.result.Attribute("message").Value
will not work because theXElement.Attribute(XName)
method selects an XML attribute rather than an element.
Putting those two points together, your code should look like:
private static List<TestResults> GetTestAutomationExecutionResult(string filePath)
=> GetTestAutomationExecutionResult(XElement.Load(filePath));
private static List<TestResults> GetTestAutomationExecutionResult(XElement xelement)
{
var query = from e in xelement.Descendants()
where e.Name.LocalName == "test"
let r = e.Attribute("result").Value
let m = r == "Fail" ? e.Elements("failure").Elements("message").FirstOrDefault()?.Value : ""
select new TestResults(r, m);
return query.ToList();
}
Demo fiddle here.