以下是我的XML示例。有很多类似的案例。
<suite name="regression_1">
<test name="Login check" id="s1-t1">
<tc name="Valid Username & Password">
<message level="INFO" timestamp="20170726 14:25:39.778">Return: None</message>
<status starttime="20170726 14:25:39.740" status="PASS"/>
</tc>
<tc name="Invalid Username or Password">
<message level="INFO" timestamp="20170726 14:25:39.779">Return error</message>
<tc name="Invalid password" library="avi_lib">
<message level="TRACE" timestamp="20170726 14:25:47.769">Return error</message>
<status starttime="20170726 14:25:39.779" status="FAIL"/>
</tc>
<status starttime="20170726 14:25:39.738" status="FAIL"/>
</tc>
<status status="FAIL"/>
</test>
</suite>
我的要求: 通过xml日志,记下测试,测试用例和测试用例状态。如果状态失败,则显示其失败的测试用例和测试套件以及其他相关消息。
问题我面临的问题:我正在迭代测试,收集所有子测试状态和状态。在下面的代码中,如果tc#2失败,则输出为tc1,因为我通过收集列表中的所有状态来迭代tc1。所以输出会重复出现。
我想要的输出(仅适用于状态=&#34;失败&#34;)
测试名称:登录检查
测试用例:用户名无效&amp;密码
状态:失败
消息:返回错误
以下是我的代码:
# !/usr/bin/python
from xml.dom.minidom import parse
import xml.dom.minidom
import time
DOMTree = xml.dom.minidom.parse("output.xml")
collection = DOMTree.documentElement
tc_entry = collection.getElementsByTagName("suite")
for tc in tc_entry:
if tc.hasAttribute("name"):
print ("Suite name: {}".format(tc.getAttribute("name")))
tests = tc.getElementsByTagName('test')
for test in tests:
testcases = test.getElementsByTagName('tc')
for tc_name in testcases:
status = tc_name.getElementsByTagName('status')
for state in status:
if state.getAttribute("status") != "PASS":
print("Failed")
print("Test name: {}".format(test.getAttribute("name")))
print("Test case name: {}".format(tc_name.getAttribute("name")))
print("Status: {}".format(state.getAttribute("status")))
答案 0 :(得分:0)
不知道我是否理解正确...但是,尝试使用这样的递归函数:
# !/usr/bin/python
from xml.dom.minidom import parse
import xml.dom.minidom
import time
def getStatusForNode(tc):
status_to_be_returned = []
is_just_father = False
for child in tc.childNodes:
if child.nodeName == "tc":
is_just_father = True
status_to_be_returned.append(getStatusForNode(child)[0])
if not is_just_father:
status = tc.getElementsByTagName('status')
return [(tc, status)]
return status_to_be_returned
DOMTree = xml.dom.minidom.parse("output.xml")
collection = DOMTree.documentElement
tc_entry = collection.getElementsByTagName("suite")
for tc in tc_entry:
if tc.hasAttribute("name"):
print("Suite name: {}".format(tc.getAttribute("name")))
tests = tc.getElementsByTagName('test')
for test in tests:
for child in test.childNodes:
if child.nodeName == "tc":
children_status = getStatusForNode(child)
for (tc_name, status) in children_status:
for state in status:
if state.getAttribute("status") != "PASS":
print("---")
print("Test name: {}".format(test.getAttribute("name")))
print("Test case name: {}".format(tc_name.getAttribute("name")))
print("Status: {}".format(state.getAttribute("status")))
希望这有帮助
再见
戴夫
答案 1 :(得分:0)
我建议使用XPath表达式:
注意:在我的示例中,我只使用了一个suite
元素,因此我将其称为root
- 在您的实现中,您需要遍历所有suite
因此,root
元素会有所不同,例如第tests = root.findall('.//tc')
行将成为tests = s.findall('.//tc')
。我已经评论了我认为你会使用的线条。
import xml.etree.ElementTree as et
tree = et.parse('some_file.xml')
root = tree.getroot()
# suites = root.findall('.//suite')
# for s in suites:
tests = root.findall('.//tc') # Grab all 'tc' elements within a 'suite' element
test_name = root.find('test').attrib['name']
for tc in tests:
status = tc.find('status').attrib['status'].lower()
if 'fail' in status:
tc_name = tc.attrib['name']
msg = tc.find('message').text
print("Test Name: {}\nTest Case: {}\nStatus: {}\nMessage: {}\n".format(
test_name, tc_name, status.capitalize(), msg
))
输出:
Test Name: Login check
Test Case: Invalid Username or Password
Status: Fail
Message: Return error
Test Name: Login check
Test Case: Invalid password
Status: Fail
Message: Return error
此外,Python的xml.etree.ElementTree文档中还有XPath信息。