使用 XElement 解析 XUnit XML 文件中的多个元素时出现问题
Problem parsing through multiple elements in the XUnit XML file using XElement
我在使用 XElement 通过 XUnit XML 文件和 return 值解析多个元素时遇到问题。
这是 XML 文件
<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>
我可以使用此代码解析 test 元素。
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, ""));
}
}
但我很难在 foreach 的 failure 元素中查找和添加消息。
result.Attribute("message").Value
您的代码有几个问题:
<result>
元素不是根元素的直接子元素,因此 xelement.Elements().Where(e => e.Name.LocalName == "test")
没有 select 任何东西。您需要深入到层次结构中,例如Descendants()
.
消息文本包含在 <test>
节点的间接子元素中,特别是 failure/message
。您需要 select 此元素才能获取消息。
result.Attribute("message").Value
将不起作用,因为 XElement.Attribute(XName)
method selects an XML attribute rather than an element.
参见:XML attribute vs XML element。
将这两点放在一起,您的代码应该如下所示:
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();
}
演示 fiddle here.
我在使用 XElement 通过 XUnit XML 文件和 return 值解析多个元素时遇到问题。
这是 XML 文件
<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>
我可以使用此代码解析 test 元素。
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, ""));
}
}
但我很难在 foreach 的 failure 元素中查找和添加消息。
result.Attribute("message").Value
您的代码有几个问题:
<result>
元素不是根元素的直接子元素,因此xelement.Elements().Where(e => e.Name.LocalName == "test")
没有 select 任何东西。您需要深入到层次结构中,例如Descendants()
.消息文本包含在
<test>
节点的间接子元素中,特别是failure/message
。您需要 select 此元素才能获取消息。result.Attribute("message").Value
将不起作用,因为XElement.Attribute(XName)
method selects an XML attribute rather than an element.参见:XML attribute vs XML element。
将这两点放在一起,您的代码应该如下所示:
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();
}
演示 fiddle here.