script/Testlink转换工具/XmlToExcel3/XmlToExcel.py

282 lines
9.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding:utf-8 -*-
# 日期2019年9月9日
# 作者Wang WenJie
# 版本1.2.1
# 说明用于TestLink导出后的Xml文件转成Excel文件
import xlwt
from xml.dom.minidom import parse, Node
import os
import re
import json
class XmlToExcel(object):
'''
TestLink导出的xml文件转Excel
构造字典树读取xml文件
'''
def __init__(self):
# 全局字典树
self.__xml_tree = []
def __getText(self, node):
'''
获取节点的文本内容
Args:
node: 节点
Returns:
节点中的文本
'''
if node is None:
return ''
if node.nodeType in [Node.TEXT_NODE, Node.CDATA_SECTION_NODE]:
# return node.nodeValue
return node.wholeText
else:
return ''
def __get_importance(self, num):
'''
重要性序号转换成对应的中文
'''
if num == '1':
return ''
elif num == '2':
return ''
elif num == '3':
return ''
return num
def __get_exec_type(self, num):
'''
执行方式序号转换成对应的中文
'''
if num == '1':
return '手工'
elif num == '2':
return '自动的'
return num
def __read_cases(self, case):
'''
读单个testcase节点并返回字典
'''
case_dic = {}
# 节点名称,即对应的标题
case_dic['casename'] = case.getAttribute('name')
case_row = 0
for child in case.childNodes:
# 如果遇到换行会读出TEXT_NODE所以加上判断
if child.nodeType == Node.ELEMENT_NODE:
# 摘要和前提
if child.tagName in ['summary', 'preconditions']:
case_dic[child.tagName] = self.__getText(child.firstChild)
elif child.tagName == 'importance': # 重要性
num = self.__getText(child.firstChild)
case_dic[child.tagName] = self.__get_importance(num)
elif child.tagName == 'execution_type': # 执行方式
num = self.__getText(child.firstChild)
case_dic[child.tagName] = self.__get_exec_type(num)
elif child.tagName == 'steps': # 步骤
case_dic['steps'] = []
for steps in child.getElementsByTagName('step'):
step_dic = {}
case_row = case_row + 1
for step in steps.childNodes:
if step.nodeType == Node.ELEMENT_NODE:
if step.tagName in ['actions', 'expectedresults']:
step_dic[step.tagName] = self.__getText(step.firstChild)
case_dic['steps'].append(step_dic)
# 记录有多少步
case_dic['row'] = case_row
return case_dic
def __read_suites(self, root):
'''
读模块下的testsuite
'''
suites = []
for testsuite in root.getElementsByTagName('testsuite'):
module_tree = {}
# 模块名
module = testsuite.getAttribute('name')
module_tree['module'] = module
module_tree['testcase'] = []
module_row = 0
for case in testsuite.getElementsByTagName('testcase'):
case_dic = self.__read_cases(case)
module_row = module_row + case_dic['row']
module_tree['testcase'].append(case_dic)
# 记录模块占多少行
module_tree['row'] = module_row
suites.append(module_tree)
return suites
def __read_single(self, root):
'''
读单节点用例
'''
suites = []
module_tree = {}
module_tree['module'] = ''
module_tree['testcase'] = []
module_row = 0
testcase = root.getElementsByTagName('testcase')
for case in testcase:
case_dic = self.__read_cases(case)
module_row = module_row + case_dic['row']
# 记录模块占多少行
module_tree['row'] = module_row
suites.append(module_tree)
return suites
def read_xml(self, xml_files):
'''
读xml文件主要方法
Args:
xml_files: xml文件路径
'''
# 统计
result = {}
result['success'] = 0
result['fail'] = 0
for file in xml_files:
xml_dic = {}
try:
dom = parse(file)
except:
print('ERROR: 载入文件失败[{}]'.format(file))
result['fail'] = result['fail'] + 1
continue
# 选择根节点
root = dom.documentElement
if root.nodeName == 'testsuite': # 多用例集
suites = self.__read_suites(root)
# 一级模块名即sheet页名
sheet_name = root.getAttribute('name')
if sheet_name.strip() == '':
raise ValueError("xml文件有误, 请检查testsuite的name属性, 不能为空.");
elif root.nodeName == 'testcases': # 单个用例
suites = self.__read_single(root)
sheet_name = 'single'
else:
print('ERROR: 文件不是TestLink标准格式')
result['fail'] = result['fail'] + 1
continue
xml_dic[sheet_name] = suites
xml_dic['sheet_name'] = sheet_name
self.__xml_tree.append(xml_dic)
result['success'] = result['success'] + 1
return result
def set_style(self, height = 12, align = 'center'):
'''
设置写入单元格样式,包括文字大小,对齐方式
'''
# 字体样式
font = xlwt.Font()
font.height = height * 20
font.name = '宋体'
# 对齐方式
alignment = xlwt.Alignment()
# 居中
if align == 'center':
alignment.horz = xlwt.Alignment.HORZ_CENTER
elif align == 'left': # 左对齐
alignment.horz = xlwt.Alignment.HORZ_LEFT
alignment.vert = xlwt.Alignment.VERT_CENTER
alignment.wrap = 1 # 自动换行
style = xlwt.XFStyle()
style.alignment = alignment
style.font = font
return style
def __auto_break(self, text):
'''
将html标记清除并替换成对应的换行符
'''
symbol = ('<p>', '</p>', '&nbsp;')
for s in symbol:
text = re.sub(s, '', text, flags=re.M|re.I|re.S)
# 替换为换行
text = re.sub(r'<.+[/]{1}>|<[/]{1}.>|<br>', r'\n', text, flags=re.M|re.I|re.S)
return text.strip()
def write_excel(self, file_name):
'''
将构造的字典树写入Excel文件中
'''
workbook = xlwt.Workbook(encoding='utf-8')
size = 100
# 标题
titles = (('模块', 35), ('用例标题', 50), ('重要性', 25), ('执行方式', 27), ('摘要', 80), ('前提', 80), ('步骤', 160), ('结果', 160))
result = {}
result['module'] = 0
result['case'] = 0
for sheet in self.__xml_tree:
sheet_name = sheet.get('sheet_name')
# 插入sheet名称
worksheet = workbook.add_sheet(sheet_name)
col = 0
row = 1
end = 0
title_row = 1
title_end = 0
# 写入标题
for t, w in titles:
width = w * size
worksheet.write(0, col, t, self.set_style(11))
worksheet.col(col).width = width
col = col + 1
# 写模块
for module in sheet.get(sheet_name):
# 写模块名
end = row + int(module.get('row')) - 1
worksheet.write_merge(row, end, 0, 0, module.get('module'), self.set_style(12))
row = end + 1 # 更新模块列
center = self.set_style()
left = self.set_style(align='left')
# 写用例
for case in module.get('testcase'):
title_end = int(case.get('row')) + title_row - 1
worksheet.write_merge(title_row, title_end, 1, 1, case.get('casename'), center)
worksheet.write_merge(title_row, title_end, 2, 2, case.get('importance'), center)
worksheet.write_merge(title_row, title_end, 3, 3, case.get('execution_type'), center)
summary = case.get('summary')
worksheet.write_merge(title_row, title_end, 4, 4, self.__auto_break(summary), left)
prec = case.get('preconditions')
worksheet.write_merge(title_row, title_end, 5, 5, self.__auto_break(prec), left)
# 步骤
step_row = title_row
for step in case.get('steps'):
actions = step.get('actions')
worksheet.write(step_row, 6, self.__auto_break(actions), left)
results = step.get('expectedresults')
worksheet.write(step_row, 7, self.__auto_break(results), left)
step_row = step_row + 1
title_row = title_end + 1
# 用例数+1
result['case'] = result['case'] + 1
# 模块数+1
result['module'] = result['module'] + 1
# 写入Excel
workbook.save(file_name)
return result
if __name__ == "__main__":
file = [os.path.join(os.getcwd(), 'test.xml')]
excel = os.path.join(os.getcwd(), 'test.xls')
dom = XmlToExcel()
dom.read_xml(file)
dom.write_excel(excel)