TestLink导出用例转换工具(XML2Excel)
因工作需要将Testlink用例导出为Excel文件,借鉴网上部分代码后实现。
功能为:从TestLink导出的用例或用例集,通过工具转换为Excel文件,界面显示转换的每条用例,统计每次转换的用例数。
已编译为EXE文件,可直接下载: TestLink导出XML用例转换为Excel工具-IT管理文档类资源-CSDN下载
源代码如下:
# -*- coding: utf-8 -*-
"""
-------------------------------------------------File Name: xml2xlsx.pyAuthor : 曾良均QQ: 277099728Date: 8/9/2022 8:49 AM Description :
-------------------------------------------------Change Activity:-------------------------------------------------
"""import os, base64
import time
import logging
import xml
from fav import img
import re
try:from lxml import etree
except ImportError:import xml.etree.cElementTree as etree
import tkinter
from tkinter import messagebox
from tkinter import filedialog
from tkinter import *
import xlwt
import xml.dom.minidomt1 = []
root = None
# 获取当前有时间,用于输出日志
fmt = time.strftime("%m/%d %H:%M:%S", time.localtime()) + '>> '__author__ = {'name': '曾良均','QQ': '277099728','Email': 'zlj-316731@163.com','Blog': 'https://blog.csdn.net/zljun8210','Created': '2017-07-03'}# 设置logger配置
logging.basicConfig(level=logging.DEBUG,encoding='utf-8',format='%(asctime)s %(message)s',datefmt='%a, %d %b %Y %H:%M:%S',filename='./test.log',filemode='w')class Converter():path = "./"def __init__(self, rt):if rt is None:self.t = tkinter.Tk()else:self.t = tkinter.Toplevel(rt)self.t.title("xml2xls转换器")# 设置窗口图标self.setIcon()self.t.geometry('600x400')self.lab_input = Label(self.t, font=("微软雅黑", 9, "bold"), text=" 源文件: ")self.lab_input.place(x=2, y=20)self.ent = Entry(self.t, bd=1)self.ent.place(x=80, y=20, width=250)self.btn = Button(self.t, font=("微软雅黑", 9, "bold"), text=" 打开 ", command=self.callback)self.btn.place(x=350, y=20)self.btn_exe1 = Button(self.t, font=("微软雅黑", 9, "bold"), text=" 转换用例 ", command=self.tcConvert)self.btn_exe1.place(x=410, y=20)self.btn_exe2 = Button(self.t, font=("微软雅黑", 9, "bold"), text=" 转换用例集 ", command=self.tcConverts)self.btn_exe2.place(x=500, y=20)self.lab_info = Label(self.t, fg='red', font=("微软雅黑", 7, "bold underline"), text="注意:转换用例集,因TestLink导出的两级测试用例集,其xml文件最外层testsuite,须手动改为testsuites")self.lab_info.place(x=15, y=55)self.st = Text(self.t, wrap='word')self.st.place(x=5, y=80, width=560, height=260)self.st.configure(state=tkinter.DISABLED)sb = Scrollbar(self.st, orient=VERTICAL)sb["command"] = self.st.yview()self.st["yscrollcommand"] = sb.setsb.pack(side=RIGHT, fill='both')self.labinfo = Label(self.t, font=("微软雅黑", 7, "bold"), text=" Testlink软件之XML转Excel工具 \n 作者:曾良均 \n Ver: 0.1 (20220809) ")self.labinfo.place(x=420, y=350)def setIcon(self):tmp = open("tmp.ico", "wb+")tmp.write(base64.b64decode(img))tmp.close()self.t.iconbitmap("tmp.ico")os.remove("tmp.ico")# 选取文件路径def callback(self):self.ent.delete(0, END)filepath = filedialog.askopenfilename()if filepath:self.ent.insert(0, filepath) # 将选择好的路径加入到entry里面@staticmethoddef openfilename():filename = filedialog.asksaveasfilename(filetypes=[("打开文件", "*.xml")])if filename:return open(filename, 'w', encoding='utf8')# 转换测试用例def tcConvert(self):path = self.ent.get()logging.debug('转换的XML文件为 ' + path)self.st.configure(state=tkinter.NORMAL)# 用于清空文本框内容self.st.insert(tkinter.END, '转换的XML文件为 ' + path + '\n')tfn = path.split("/")[-1]ofn = tfn.split(".")[0]# print("文件名是: " + ofn)self.st.insert(tkinter.END, '转换后的文件名是: ' + ofn + '.xls')self.st.see(tkinter.END)logging.debug('转换后的文件名: ' + ofn + '.xls')if path == "":tkinter.messagebox.showinfo("Messages", "请打开有效的xml文件!")dom = xml.dom.minidom.parse(path)# 写入excel中workbook = xlwt.Workbook(encoding="utf-8")# 创建sheet名称booksheet = workbook.add_sheet(ofn)# 设置excel宽度booksheet.col(0).width = 5120booksheet.col(1).width = 5120booksheet.col(2).width = 5120booksheet.col(3).width = 5120booksheet.col(4).width = 5120booksheet.col(5).width = 5120borders = xlwt.Borders()borders.left = 1borders.right = 1borders.top = 1borders.bottom = 1# 设置头部文件字体格式等title = xlwt.easyxf(u'font:name 仿宋,height 240 ,colour_index black, bold on, italic off; align: wrap on, vert centre, horiz center;pattern: pattern solid, fore_colour light_orange;')# 设置写入文件的格式style = xlwt.easyxf('align: wrap on,vert centre, horiz center')if dom:logging.debug(" ---- 开始转换 ---- ")self.st.insert(tkinter.END, "\n ---- 开始转换 ---- \n" + '\n')self.st.update()# 设置excel字段item = '模块/任务'Subitem = '用例名称'CaseTitle = '描述'Condition = '前置条件'actions = '操作步骤'Result = '预期结果'booksheet.write(0, 0, item, title)booksheet.write(0, 1, Subitem, title)booksheet.write(0, 2, CaseTitle, title)booksheet.write(0, 3, Condition, title)booksheet.write(0, 4, actions, title)booksheet.write(0, 5, Result, title)k = 0try:testcases_tag = dom.getElementsByTagName('testsuite')fun = testcases_tag[0].getAttribute('name')except:testcases_tag = dom.getElementsByTagName('testcases')fun = '功能测试' # 此时没有父级名称,直接设置为功能测试finally:testcase_tag_ = testcases_tag[0].getElementsByTagName('testcase')for j in range(len(testcase_tag_)):step_tag_ = testcases_tag[0].getElementsByTagName('testcase')[j].getElementsByTagName('steps')[0].getElementsByTagName('step')# print(step_tag_)for i in range(len(step_tag_)):# k的值向上递增k = k + 1# 获取用例名称try:testcase_tag_name = testcases_tag[0].getElementsByTagName('testcase')[j].getAttribute('name')# 写入excel中logging.debug(f'第 {k} 条用例: {testcase_tag_name}')self.st.insert(tkinter.END, fmt + f'第 {k} 条用例: {testcase_tag_name}' + '\n')self.st.see(tkinter.END)self.st.update()except:testcase_tag_name = ''booksheet.write(k, 1, testcase_tag_name, style)# 获取用例描述try:testcase_tab_summary = \testcases_tag[0].getElementsByTagName('testcase')[j].getElementsByTagName('summary')[0].firstChild.datatestcase_tab_summary = re.sub(r'<(p|/br|br|/p|br/)*>', '\n', testcase_tab_summary)except:testcase_tab_summary = ''booksheet.write(k, 2, testcase_tab_summary, style)# 获取前置条件try:testcase_tag_preconditions = \testcases_tag[0].getElementsByTagName('testcase')[j].getElementsByTagName('preconditions')[0].firstChild.datatestcase_tag_preconditions = re.sub(r'<(p|/br|br|/p|br/)*>', '\n', testcase_tag_preconditions)except:testcase_tag_preconditions = ''booksheet.write(k, 3, testcase_tag_preconditions, style)# 获取操作步骤try:step_number = \testcases_tag[0].getElementsByTagName('testcase')[j].getElementsByTagName('steps')[0].getElementsByTagName('step')[i].getElementsByTagName('step_number')[0].firstChild.dataexcept:step_number = 0# 进行替换step_number = re.sub(r'<(p|/br|br|/p|br/)*>', '\n', step_number)# 获取用例步骤try:step = testcases_tag[0].getElementsByTagName('testcase')[j].getElementsByTagName('steps')[0].getElementsByTagName('step')[i].getElementsByTagName('actions')[0].firstChild.datastep = re.sub(r'<(p|/br|br|/p|br/)*>', '\n', step)except:step = ''# 将得到文件写入excel中booksheet.write(k, 4, step, style)booksheet.write(k, 0, fun, style)# 获取预期结果try:expectedresults = \testcases_tag[0].getElementsByTagName('testcase')[j].getElementsByTagName('steps')[0].getElementsByTagName('step')[i].getElementsByTagName('expectedresults')[0].firstChild.dataexpectedresults = re.sub(r'<(p|/br|br|/p|br/)*>', '\n', expectedresults)except:expectedresults = ''booksheet.write(k, 5, expectedresults, style)# 保存至本地pathlist = path.split("/")pathlist.pop()newpath = '/'.join(pathlist)workbook.save('{}.xls'.format(newpath + "/" + ofn))logging.debug('测试用例转换完成!!\n')logging.debug(f'此次转换了{k} 条用例\n\n')self.st.insert(tkinter.END, '\n' + '测试用例转换完成!!' + '\n')self.st.insert(tkinter.END, fmt + f'此次转换了{k} 条用例' + '\n\n')self.st.see(tkinter.END)self.st.update()self.st.configure(state=tkinter.DISABLED)tkinter.messagebox.showinfo("Messages", "Convert Successfully.\n Save file to " + ofn + ".xls .")# 转换测试用例集def tcConverts(self):path = self.ent.get()logging.debug('转换的XML文件为 ' + path)self.st.configure(state=tkinter.NORMAL)# 用于清空文本框内容self.st.delete(1.0, tkinter.END)self.st.insert(tkinter.END, '转换的XML文件为 ' + path + '\n')tfn = path.split("/")[-1]ofn = tfn.split(".")[0]# print("文件名是: " + ofn)self.st.insert(tkinter.END, '转换后的文件名是: ' + ofn + '.xls')self.st.see(tkinter.END)logging.debug('转换后的文件名: ' + ofn + '.xls')if path == "":tkinter.messagebox.showinfo("Messages", "请打开有效的xml文件!")dom = xml.dom.minidom.parse(path)# 写入excel中workbook = xlwt.Workbook(encoding="utf-8")# 创建sheet名称booksheet = workbook.add_sheet(ofn)# 设置excel宽度booksheet.col(0).width = 5120booksheet.col(1).width = 5120booksheet.col(2).width = 5120booksheet.col(3).width = 5120booksheet.col(4).width = 5120booksheet.col(5).width = 5120borders = xlwt.Borders()borders.left = 1borders.right = 1borders.top = 1borders.bottom = 1# 设置头部文件字体格式等title = xlwt.easyxf(u'font:name 仿宋,height 240 ,colour_index black, bold on, italic off; align: wrap on, vert centre, horiz center;pattern: pattern solid, fore_colour light_orange;')# 设置写入文件的格式style = xlwt.easyxf('align: wrap on,vert centre, horiz center')if dom:logging.debug(" ---- 开始转换 ---- ")self.st.insert(tkinter.END, "\n ---- 开始转换 ---- \n" + '\n')self.st.update()# 设置excel字段item = '模块/任务'Subitem = '用例名称'CaseTitle = '描述'Condition = '前置条件'actions = '操作步骤'Result = '预期结果'booksheet.write(0, 0, item, title)booksheet.write(0, 1, Subitem, title)booksheet.write(0, 2, CaseTitle, title)booksheet.write(0, 3, Condition, title)booksheet.write(0, 4, actions, title)booksheet.write(0, 5, Result, title)# TestLink导出的两级测试用例集,其xml文件最外层testsuite需手动改为testsuitestry:testsites_tag = dom.getElementsByTagName('testsuites')try:testcases_tag = testsites_tag[0].getElementsByTagName('testsuite')except:testcases_tag = testsites_tag[0].getElementsByTagName('testcases')except:tkinter.messagebox.showinfo("Messages", "XML文件最外层对象不是testsuites,请修改后再重试。")else:k = 0for m in range(len(testcases_tag)):testcase_tag_ = testcases_tag[m].getElementsByTagName('testcase')fun = testcases_tag[m].getAttribute('name')for j in range(len(testcase_tag_)):step_tag_ = testcases_tag[m].getElementsByTagName('testcase')[j].getElementsByTagName('steps')[0].getElementsByTagName('step')# print(step_tag_)for i in range(len(step_tag_)):# k的值向上递增k = k + 1# 获取用例名称try:testcase_tag_name = testcases_tag[m].getElementsByTagName('testcase')[j].getAttribute('name')# 写入excel中logging.debug(f'第 {k} 条用例: {testcase_tag_name}')self.st.insert(tkinter.END, fmt + f'第 {k} 条用例: {testcase_tag_name}' + '\n')self.st.see(tkinter.END)self.st.update()except:testcase_tag_name = ''booksheet.write(k, 1, testcase_tag_name, style)# 获取用例描述try:testcase_tab_summary = \testcases_tag[m].getElementsByTagName('testcase')[j].getElementsByTagName('summary')[0].firstChild.datatestcase_tab_summary = re.sub(r'<(p|/br|br|/p|br/)*>', '\n', testcase_tab_summary)except:testcase_tab_summary = ''booksheet.write(k, 2, testcase_tab_summary, style)# 获取前置条件try:testcase_tag_preconditions = \testcases_tag[m].getElementsByTagName('testcase')[j].getElementsByTagName('preconditions')[0].firstChild.datatestcase_tag_preconditions = re.sub(r'<(p|/br|br|/p|br/)*>', '\n', testcase_tag_preconditions)except:testcase_tag_preconditions = ''booksheet.write(k, 3, testcase_tag_preconditions, style)# 获取操作步骤try:step_number = \testcases_tag[m].getElementsByTagName('testcase')[j].getElementsByTagName('steps')[0].getElementsByTagName('step')[i].getElementsByTagName('step_number')[0].firstChild.dataexcept:step_number = 0# 进行替换step_number = re.sub(r'<(p|/br|br|/p|br/)*>', '\n', step_number)# 获取用例步骤try:step = testcases_tag[m].getElementsByTagName('testcase')[j].getElementsByTagName('steps')[0].getElementsByTagName('step')[i].getElementsByTagName('actions')[0].firstChild.datastep = re.sub(r'<(p|/br|br|/p|br/)*>', '\n', step)except:step = ''# 将得到文件写入excel中booksheet.write(k, 4, step, style)booksheet.write(k, 0, fun, style)# 获取预期结果try:expectedresults = \testcases_tag[m].getElementsByTagName('testcase')[j].getElementsByTagName('steps')[0].getElementsByTagName('step')[i].getElementsByTagName('expectedresults')[0].firstChild.dataexpectedresults = re.sub(r'<(p|/br|br|/p|br/)*>', '\n', expectedresults)except:expectedresults = ''booksheet.write(k, 5, expectedresults, style)# 保存至本地pathlist = path.split("/")pathlist.pop()newpath = '/'.join(pathlist)workbook.save('{}.xls'.format(newpath + "/" + ofn))logging.debug('测试用例转换完成!!\n')logging.debug(f'此次转换了{k} 条用例\n\n')self.st.insert(tkinter.END, '\n' + '测试用例转换完成!!' + '\n')self.st.insert(tkinter.END, fmt + f'此次转换了{k} 条用例' + '\n\n')self.st.see(tkinter.END)self.st.update()self.st.configure(state=tkinter.DISABLED)tkinter.messagebox.showinfo("Messages", "Convert Successfully.\n Save file to " + ofn + ".xls .")if __name__ == '__main__':root = Nonet1.append(Converter(root))root = t1[0].troot.mainloop()
运行界面:
转换后的Excel文件如下:
如需其他字段,可自行调整源码。
关于icon即logo图标实现,代码如下:
#! encoding:utf-8
import base64__author__ = {'name': '曾良均','QQ': '277099728','Email': 'zlj-316731@163.com','Blog': 'https://blog.csdn.net/zljun8210','Created': '2017-07-03'}open_icon = open("favicon.ico", "rb") # 要放入的图标文件
b64str = base64.b64encode(open_icon.read()) # 以Base64的格式读出
open_icon.close()
write_data = "img=%s" % b64str
f = open("fav.py", "w+")
f.write(write_data)
f.close()
TestLink导出用例转换工具(XML2Excel)相关推荐
- testlink用例转换导入
testlink用例转换导入 我们在用testlink进行用例管理的时候,发现用例不能用excel进入导入,只支持xml文件格式的导入,这对我们写用例来说是不太方便的. 我自己开发了一个testlin ...
- TestLink在线Excel用例转换xml
[原文链接]:https://blog.tecchen.xyz ,博文同步发布到博客园. 由于精力有限,对文章的更新可能不能及时同步,请点击上面的原文链接访问最新内容. 欢迎访问我的个人网站:http ...
- 华为Atlas200DK开发从零开始3.目标检测模型CANN部署——以YOLOX、YOLOv5和Nanodet为例(2)CANN模型的转换,ATC转换工具
目录 前言 深度学习模型在AI芯片上部署的一般流程 通过ATC工具进行模型转换 ATC工具使用流程 模型转换步骤 1.其他框架转onnx 2. onnx模型修改与优化 3.使用ATC转换 后记 前言 ...
- 转换onnx_模型转换工具X2Paddle操作大全
深度学习的应用主要包括两个部分,一是通过深度学习框架训练出模型,二是利用训练出来的模型进行预测. 开发者基于不同的深度学习框架能够得到不同的训练模型,如果想要基于一种框架进行预测,就必须要解决不同框架 ...
- bat 等待输入_深蓝词库转换 - 简单的输入法词库转换工具
深蓝词库转换 是一款 输入法词库转换 软件,支持包括 搜狗拼音.QQ拼音.Windows 10 微软拼音 在内的超过 20 种的输入法工具和词库.该程序支持 批量转换(一次拖拽多个词库文件,或者按住 ...
- 如何快速不借用转换工具将FLV格式视频转换成MP4
FLV流媒体格式是一种新的视频格式,全称为Flash Video.它的出现有效地解决了视频文件导入Flash后,使导出的SWF文件体积庞大,所以就引出了FLV格式,主要特点就是体积小 适合作为流媒体在 ...
- 3D格式转换工具HOOPS Exchange最全技术指南(二):4大功能特征与典型使用场景
什么是 HOOPS Exchange? HOOPS Exchange 是一组软件库,可以帮助开发人员在开发应用程序时读取和写入主流的 2D 和 3D 格式.HOOPS Exchange 支持 在主流的 ...
- 视频可以转换html,10 个免费的 HTML 视频转换工具
现在,人们都喜欢看视频目前,大多数的人都是看视频在线或移动.因此,视频必须有正确的格式,可以通过手机或支持系统.因此,人们需要一些应用程序的工具,将有助于他们现有的文件格式转换成当前的格式如MP4,W ...
- 视频格式转换工具使用
还记得世界杯期间的那个"神奇教练"米卢吗?在给球员讲解战术.观摩对手比赛的时候,他总是喜欢随身携带一个小巧的摄像机.的确,有些摄像机重量很轻,几乎与普通照相机相仿,拍摄.携带和输出 ...
最新文章
- mysql 实时聚合分析,mysql累积聚合原理与用法实例分析
- pycharm如何设置注释的字体颜色
- java.lang.Enum
- leetcode2 两数相加
- html位置下移像素点,吃透移动端 1px的具体用法
- EOJ Monthly 2019.11 E. 数学题(反演 + 杜教筛 + 拉格朗日插值)
- 别学了!这 5 种即将消亡的编程语言
- 悬镜服务器系统,悬镜服务器卫士V3.3.0.3961更新通知
- 数组维度超过了支持的范围_数组公式基础:多值和单值结果_
- angular路由模块(二)
- [JavaScript]面向对象编程
- 19. jQuery 遍历
- win7下IDEA黑色主题看不到鼠标指针的修改方式
- win10 家庭版升级win11
- plc梯形图转c语言,plc梯形图转换成stl程序的实例教程
- 嵌入式系统开发笔记0_0:目录
- 紫装の槍使い(トゥーヴァ) / 紫枪(异时层土法)
- echarts 实现横坐标只显示第一个和最后一个自定义的内容
- 大连三家软件企业入围全国软件百强排行榜
- Windowns10配置安装Seata14.0(注册中心和配置中心用的都是nacos)
热门文章
- 工业电柜空调 工业电柜空调Eco模式 拓展温度冷热板 机架式循环冷却装置 水冷式冷却器 热交换与冷藏 热电冷却 热电冷却器 热电冷板 热电外壳冷却器 热电板冷却器 热电空调 电热冷却台 电热电柜空调
- 小白扫盲——双系统装机
- win10 中谷歌浏览器安装的插件位置
- php中基本符号,PHP中的基本符号及方法
- 手把手带你了解时间复杂度和空间复杂度 【超详细】
- 游戏蓝牙耳机哪款好?年末盘点:高性价比低延迟蓝牙耳机排名
- 新手入门:认识wifi的无线信道
- 程序员进阶升级全攻略
- seo从入门到精通_SEM必读书单丨从入门到精通,这9本书就是你的钥匙!
- SE API第10/11天:集合 ——>ArrayListals、Iterator遍历迭代器、增强for、List集→subList、集合间转换asList、排序sort | Map相关