我是C#和XML反序列化的新手,请原谅我输入的任何错误单词/信息不正确。
我正在反序列化带有根元素的Nunit3测试结果XML,因为test-run和子元素分别是测试套件和测试用例。
测试用例会重复执行多次,具体取决于执行的测试用例的数量以及我感兴趣的元素。
Nunit XML的C#类如下。
[XmlRoot(ElementName = "test-run")]
public class Testrun
{
[XmlElement(ElementName = "command-line")]
public string Commandline { get; set; }
[XmlElement(ElementName = "test-suite")]
public Testsuite Testsuite { get; set; }
}
[XmlRoot(ElementName = "test-suite")]
public class Testsuite
{
[XmlElement(ElementName = "test-case")]
public Testcase Testcase { get; set; }
}
但是有时嵌套的测试套件元素会在Nunit XML中出现,如下所示。
<test-suite type="TestSuite" id="0-1005" name="TopGearFramework" fullname="TopGearFramework" runstate="Runnable" testcasecount="2" result="Failed" site="Child" start-time="2019-02-21 04:17:28Z" end-time="2019-02-21 04:19:16Z" duration="108.354384" total="2" passed="1" failed="1" warnings="0" inconclusive="0" skipped="0" asserts="14">
<test-suite type="TestSuite" id="0-1006" name="CFTestCases" fullname="TopGearFramework.CFTestCases" runstate="Runnable" testcasecount="2" result="Failed" site="Child" start-time="2019-02-21 04:17:28Z" end-time="2019-02-21 04:19:16Z" duration="108.353019" total="2" passed="1" failed="1" warnings="0" inconclusive="0" skipped="0" asserts="14">
<test-suite type="TestSuite" id="0-1007" name="PoCTestCases" fullname="TopGearFramework.CFTestCases.PoCTestCases" runstate="Runnable" testcasecount="2" result="Failed" site="Child" start-time="2019-02-21 04:17:28Z" end-time="2019-02-21 04:19:16Z" duration="108.352989" total="2" passed="1" failed="1" warnings="0" inconclusive="0" skipped="0" asserts="14">
<test-suite type="TestSuite" id="0-1008" name="FeatureFiles" fullname="TopGearFramework.CFTestCases.PoCTestCases.FeatureFiles" runstate="Runnable" testcasecount="2" result="Failed" site="Child" start-time="2019-02-21 04:17:28Z" end-time="2019-02-21 04:19:16Z" duration="108.352968" total="2" passed="1" failed="1" warnings="0" inconclusive="0" skipped="0" asserts="14">
<test-suite type="TestFixture" id="0-1002" name="IndividualDealerPartyCreationFeature" fullname="TopGearFramework.CFTestCases.PoCTestCases.FeatureFiles.IndividualDealerPartyCreationFeature" classname="TopGearFramework.CFTestCases.PoCTestCases.FeatureFiles.IndividualDealerPartyCreationFeature" runstate="Runnable" testcasecount="1" result="Passed" start-time="2019-02-21 04:17:28Z" end-time="2019-02-21 04:19:07Z" duration="99.414157" total="1" passed="1" failed="0" warnings="0" inconclusive="0" skipped="0" asserts="10">
<test-case id="0-1003" name="XF_PAM_004_CheckNewDealerPartyCreationForIndividual" fullname="TopGearFramework.CFTestCases.PoCTestCases.FeatureFiles.IndividualDealerPartyCreationFeature.XF_PAM_004_CheckNewDealerPartyCreationForIndividual" methodname="XF_PAM_004_CheckNewDealerPartyCreationForIndividual" classname="TopGearFramework.CFTestCases.PoCTestCases.FeatureFiles.IndividualDealerPartyCreationFeature" runstate="Runnable" seed="293675085" result="Passed" start-time="2019-02-21 04:17:29Z" end-time="2019-02-21 04:19:07Z" duration="98.585096" asserts="10">
请注意,在发生测试用例之前,将测试套件重复5次。在反序列化过程中,对于测试用例对象,它为空。
如何处理测试套件元素的动态嵌套或重复以获取测试用例?
谢谢。
编辑1#完整的XML复制以供参考。
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<test-run id="2" testcasecount="2" result="Failed" total="2" passed="1" failed="1" inconclusive="0" skipped="0" asserts="14" engine-version="3.9.0.0" clr-version="4.0.30319.42000" start-time="2019-02-21 04:17:25Z" end-time="2019-02-21 04:19:16Z" duration="111.183778">
<command-line><![CDATA["C:\Program Files (x86)\NUnit.org\nunit-console\nunit3-console.exe" TopGearFramework\bin\Debug\TopGearFramework.dll --result=TestResult.xml --labels=All --out=TestResult.txt]]></command-line>
<test-suite type="Assembly" id="0-1004" name="TopGearFramework.dll" fullname="TopGearFramework.dll" runstate="Runnable" testcasecount="2" result="Failed" site="Child" start-time="2019-02-21 04:17:28Z" end-time="2019-02-21 04:19:16Z" duration="108.409138" total="2" passed="1" failed="1" warnings="0" inconclusive="0" skipped="0" asserts="14">
<environment framework-version="3.11.0.0" clr-version="4.0.30319.42000" os-version="Microsoft Windows NT 10.0.16299.0" platform="Win32NT" cwd="C:\Users\qxm5789\.jenkins\workspace\TopGearTestRunner_master" machine-name="VMUC0034748" user="qxm5789" user-domain="MUC" culture="en-US" uiculture="en-US" os-architecture="x64" />
<settings>
<setting name="DisposeRunners" value="True" />
</settings>
<properties>
<property name="_PID" value="1852" />
<property name="_APPDOMAIN" value="domain-" />
</properties>
<failure>
<message><![CDATA[One or more child tests had errors]]></message>
</failure>
<test-suite type="TestSuite" id="0-1005" name="TopGearFramework" fullname="TopGearFramework" runstate="Runnable" testcasecount="2" result="Failed" site="Child" start-time="2019-02-21 04:17:28Z" end-time="2019-02-21 04:19:16Z" duration="108.354384" total="2" passed="1" failed="1" warnings="0" inconclusive="0" skipped="0" asserts="14">
<failure>
<message><![CDATA[One or more child tests had errors]]></message>
</failure>
<test-suite type="TestSuite" id="0-1006" name="CFTestCases" fullname="TopGearFramework.CFTestCases" runstate="Runnable" testcasecount="2" result="Failed" site="Child" start-time="2019-02-21 04:17:28Z" end-time="2019-02-21 04:19:16Z" duration="108.353019" total="2" passed="1" failed="1" warnings="0" inconclusive="0" skipped="0" asserts="14">
<failure>
<message><![CDATA[One or more child tests had errors]]></message>
</failure>
<test-suite type="TestSuite" id="0-1007" name="PoCTestCases" fullname="TopGearFramework.CFTestCases.PoCTestCases" runstate="Runnable" testcasecount="2" result="Failed" site="Child" start-time="2019-02-21 04:17:28Z" end-time="2019-02-21 04:19:16Z" duration="108.352989" total="2" passed="1" failed="1" warnings="0" inconclusive="0" skipped="0" asserts="14">
<failure>
<message><![CDATA[One or more child tests had errors]]></message>
</failure>
<test-suite type="TestSuite" id="0-1008" name="FeatureFiles" fullname="TopGearFramework.CFTestCases.PoCTestCases.FeatureFiles" runstate="Runnable" testcasecount="2" result="Failed" site="Child" start-time="2019-02-21 04:17:28Z" end-time="2019-02-21 04:19:16Z" duration="108.352968" total="2" passed="1" failed="1" warnings="0" inconclusive="0" skipped="0" asserts="14">
<failure>
<message><![CDATA[One or more child tests had errors]]></message>
</failure>
<test-suite type="TestFixture" id="0-1002" name="IndividualDealerPartyCreationFeature" fullname="TopGearFramework.CFTestCases.PoCTestCases.FeatureFiles.IndividualDealerPartyCreationFeature" classname="TopGearFramework.CFTestCases.PoCTestCases.FeatureFiles.IndividualDealerPartyCreationFeature" runstate="Runnable" testcasecount="1" result="Passed" start-time="2019-02-21 04:17:28Z" end-time="2019-02-21 04:19:07Z" duration="99.414157" total="1" passed="1" failed="0" warnings="0" inconclusive="0" skipped="0" asserts="10">
<properties>
<property name="Description" value="Individual Dealer Party Creation" />
</properties>
<output><![CDATA[-> Using app.config
]]></output>
<test-case id="0-1003" name="XF_PAM_004_CheckNewDealerPartyCreationForIndividual" fullname="TopGearFramework.CFTestCases.PoCTestCases.FeatureFiles.IndividualDealerPartyCreationFeature.XF_PAM_004_CheckNewDealerPartyCreationForIndividual" methodname="XF_PAM_004_CheckNewDealerPartyCreationForIndividual" classname="TopGearFramework.CFTestCases.PoCTestCases.FeatureFiles.IndividualDealerPartyCreationFeature" runstate="Runnable" seed="293675085" result="Passed" start-time="2019-02-21 04:17:29Z" end-time="2019-02-21 04:19:07Z" duration="98.585096" asserts="10">
<properties>
<property name="Description" value="XF_PAM_004_Check New Dealer Party Creation for Individual" />
</properties>
<output><![CDATA[Given Browser is launched
-> done: IndividualDealerPartyCreationSteps.GivenBrowserIsLaunched() (0.0s)
]]></output>
<attachments>
<attachment>
<filePath>C:\Users\qxm5789\.jenkins\workspace\TopGearTestRunner_master\TestResults\\XF_PAM_004_Check New Dealer Party Creation for Individual2019-02-21-11_19_02.jpg</filePath>
<description><![CDATA[Screenshot captured]]></description>
</attachment>
</attachments>
</test-case>
</test-suite>
<test-suite type="TestFixture" id="0-1000" name="TestOriginationAPIFeature" fullname="TopGearFramework.CFTestCases.PoCTestCases.FeatureFiles.TestOriginationAPIFeature" classname="TopGearFramework.CFTestCases.PoCTestCases.FeatureFiles.TestOriginationAPIFeature" runstate="Runnable" testcasecount="1" result="Failed" site="Child" start-time="2019-02-21 04:19:07Z" end-time="2019-02-21 04:19:16Z" duration="8.923635" total="1" passed="0" failed="1" warnings="0" inconclusive="0" skipped="0" asserts="4">
<properties>
<property name="Description" value="Test Origination API" />
</properties>
<failure>
<message><![CDATA[One or more child tests had errors]]></message>
</failure>
<test-case id="0-1001" name="FE_AHA_040_SearchApplicationByApplicationIDThroughOriginationAPI" fullname="TopGearFramework.CFTestCases.PoCTestCases.FeatureFiles.TestOriginationAPIFeature.FE_AHA_040_SearchApplicationByApplicationIDThroughOriginationAPI" methodname="FE_AHA_040_SearchApplicationByApplicationIDThroughOriginationAPI" classname="TopGearFramework.CFTestCases.PoCTestCases.FeatureFiles.TestOriginationAPIFeature" runstate="Runnable" seed="2107869277" result="Failed" start-time="2019-02-21 04:19:07Z" end-time="2019-02-21 04:19:16Z" duration="8.921560" asserts="4">
<properties>
<property name="Description" value="FE_AHA_040_Search Application By Application ID through Origination API" />
</properties>
<failure>
<message><![CDATA[ Error Occured:
Expected: <empty>
But was: < "Contract ID 12345 not found." >
]]></message>
<stack-trace><![CDATA[
]]></stack-trace>
</failure>
<output><![CDATA[
]]></output>
<assertions>
<assertion result="Failed">
<message><![CDATA[ Error Occured:
Expected: <empty>
But was: < "Contract ID 12345 not found." >
]]></message>
<stack-trace><![CDATA[
]]></stack-trace>
</assertion>
</assertions>
</test-case>
</test-suite>
</test-suite>
</test-suite>
</test-suite>
</test-suite>
</test-suite>
</test-run>
答案 0 :(得分:0)
如果您想以XML的任何深度获取所有<test-case>
节点,那么XDocument.Descendants("test-case")
将为您做到这一点。
如果使用result
节点中的节点,则可以使用LINQ从每个<test-case>
节点检索属性message
,并从<failure>
节点检索<test-case>
。
然后下面的代码为您提供失败消息列表以及结果。
class Program
{
public static void Main(string[] args)
{
XDocument doc = XDocument.Load(@"Path to your xml file");
var result = (from t in doc.Descendants("test-case")
from f in t.Descendants("failure")
select new
{
Result = t.Attribute("result").Value,
Failure_Message = f.Element("message") != null ? f.Element("message").Value : ""
}).ToList();
//---------------Print the result------------------
foreach (var item in result)
{
Console.WriteLine("Result: " + item.Result);
Console.WriteLine("Message: " + item.Failure_Message);
}
Console.ReadLine();
}
输出:
答案 1 :(得分:0)
您需要一个自定义解析器。我用xml linq:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication100
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
Testrun testrun = new Testrun();
testrun.ParseXml(FILENAME);
}
}
public class Testrun
{
public string Commandline { get; set; }
public Testsuite Testsuite { get; set; }
public void ParseXml(string filename)
{
XDocument doc = XDocument.Load(filename);
XElement Testrun = doc.Root;
Commandline = (string)Testrun.Element("command-line");
XElement testsuit = Testrun.Element("test-suite");
if (testsuit != null)
{
Testsuite = new Testsuite(testsuit);
}
}
}
public class Testsuite
{
public Attributes attributes { get; set; }
public Testsuite testsuite { get; set; }
public string failure_message { get; set; }
public string property_name { get; set; }
public string property_value { get; set; }
public TestCase TestCase { get; set; }
public Testsuite(XElement xTestsuite)
{
attributes = new Attributes(xTestsuite);
XElement failure = xTestsuite.Element("failure");
if (failure != null) failure_message = (string)failure.Element("message");
XElement properties = xTestsuite.Element("properties");
if (properties != null)
{
XElement property = properties.Element("property");
property_name = (string)property.Attribute("name");
property_value = (string)property.Attribute("value");
}
XElement testcase = xTestsuite.Element("test-case");
if (testcase != null)
{
TestCase = new TestCase(testcase);
}
xTestsuite = xTestsuite.Element("test-suite");
if (xTestsuite != null)
{
testsuite = new Testsuite(xTestsuite);
}
}
}
public class TestCase
{
public string output { get; set; }
public string property_name { get; set; }
public string property_value { get; set; }
public string attachment_filePath { get; set; }
public string attachment_description { get; set; }
public TestCase(XElement testCase)
{
XElement xOutput = testCase.Element("output");
if (xOutput != null) output = (string)xOutput;
XElement properties = testCase.Element("properties");
if (properties != null)
{
XElement property = properties.Element("property");
property_name = (string)property.Attribute("name");
property_value = (string)property.Attribute("value");
}
XElement attachments = testCase.Element("attachments");
if (attachments != null)
{
XElement attachment = attachments.Element("attachment");
attachment_filePath = (string)attachment.Element("filePath");
attachment_description = (string)attachment.Element ("description");
}
}
}
public class Attributes
{
string testtype { get; set; }
string id { get; set; }
string name { get; set; }
string fullname { get; set; }
string runstate { get; set; }
int testcasecount { get; set; }
string result { get; set; }
string site { get; set; }
DateTime start_time { get; set; }
DateTime end_time { get; set; }
decimal duration { get; set; }
int total { get; set; }
int passed { get; set; }
int failed { get; set; }
int warnings { get; set; }
int inconclusive { get; set; }
int skipped { get; set; }
int asserts { get; set; }
public Attributes(XElement attributes)
{
testtype = (string)attributes.Attribute("type");
id = (string)attributes.Attribute("id");
name = (string)attributes.Attribute("name");
fullname = (string)attributes.Attribute("fullname");
runstate = (string)attributes.Attribute("runstate");
testcasecount = (int)attributes.Attribute("testcasecount");
result = (string)attributes.Attribute("result");
site = (string)attributes.Attribute("site");
start_time = (DateTime)attributes.Attribute("start-time");
end_time = (DateTime)attributes.Attribute("end-time");
duration = (decimal)attributes.Attribute("duration");
total = (int)attributes.Attribute("total");
passed = (int)attributes.Attribute("passed");
failed = (int)attributes.Attribute("failed");
warnings = (int)attributes.Attribute("warnings");
inconclusive = (int)attributes.Attribute("inconclusive");
skipped = (int)attributes.Attribute("skipped");
asserts = (int)attributes.Attribute("asserts");
}
}
}