因工作需要将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)相关推荐

  1. testlink用例转换导入

    testlink用例转换导入 我们在用testlink进行用例管理的时候,发现用例不能用excel进入导入,只支持xml文件格式的导入,这对我们写用例来说是不太方便的. 我自己开发了一个testlin ...

  2. TestLink在线Excel用例转换xml

    [原文链接]:https://blog.tecchen.xyz ,博文同步发布到博客园. 由于精力有限,对文章的更新可能不能及时同步,请点击上面的原文链接访问最新内容. 欢迎访问我的个人网站:http ...

  3. 华为Atlas200DK开发从零开始3.目标检测模型CANN部署——以YOLOX、YOLOv5和Nanodet为例(2)CANN模型的转换,ATC转换工具

    目录 前言 深度学习模型在AI芯片上部署的一般流程 通过ATC工具进行模型转换 ATC工具使用流程 模型转换步骤 1.其他框架转onnx 2. onnx模型修改与优化 3.使用ATC转换 后记 前言 ...

  4. 转换onnx_模型转换工具X2Paddle操作大全

    深度学习的应用主要包括两个部分,一是通过深度学习框架训练出模型,二是利用训练出来的模型进行预测. 开发者基于不同的深度学习框架能够得到不同的训练模型,如果想要基于一种框架进行预测,就必须要解决不同框架 ...

  5. bat 等待输入_深蓝词库转换 - 简单的输入法词库转换工具

    深蓝词库转换 是一款 输入法词库转换 软件,支持包括 搜狗拼音.QQ拼音.Windows 10 微软拼音 在内的超过 20 种的输入法工具和词库.该程序支持 批量转换(一次拖拽多个词库文件,或者按住 ...

  6. 如何快速不借用转换工具将FLV格式视频转换成MP4

    FLV流媒体格式是一种新的视频格式,全称为Flash Video.它的出现有效地解决了视频文件导入Flash后,使导出的SWF文件体积庞大,所以就引出了FLV格式,主要特点就是体积小 适合作为流媒体在 ...

  7. 3D格式转换工具HOOPS Exchange最全技术指南(二):4大功能特征与典型使用场景

    什么是 HOOPS Exchange? HOOPS Exchange 是一组软件库,可以帮助开发人员在开发应用程序时读取和写入主流的 2D 和 3D 格式.HOOPS Exchange 支持 在主流的 ...

  8. 视频可以转换html,10 个免费的 HTML 视频转换工具

    现在,人们都喜欢看视频目前,大多数的人都是看视频在线或移动.因此,视频必须有正确的格式,可以通过手机或支持系统.因此,人们需要一些应用程序的工具,将有助于他们现有的文件格式转换成当前的格式如MP4,W ...

  9. 视频格式转换工具使用

    还记得世界杯期间的那个"神奇教练"米卢吗?在给球员讲解战术.观摩对手比赛的时候,他总是喜欢随身携带一个小巧的摄像机.的确,有些摄像机重量很轻,几乎与普通照相机相仿,拍摄.携带和输出 ...

最新文章

  1. mysql 实时聚合分析,mysql累积聚合原理与用法实例分析
  2. pycharm如何设置注释的字体颜色
  3. java.lang.Enum
  4. leetcode2 两数相加
  5. html位置下移像素点,吃透移动端 1px的具体用法
  6. EOJ Monthly 2019.11 E. 数学题(反演 + 杜教筛 + 拉格朗日插值)
  7. 别学了!这 5 种即将消亡的编程语言
  8. 悬镜服务器系统,悬镜服务器卫士V3.3.0.3961更新通知
  9. 数组维度超过了支持的范围_数组公式基础:多值和单值结果_
  10. angular路由模块(二)
  11. [JavaScript]面向对象编程
  12. 19. jQuery 遍历
  13. win7下IDEA黑色主题看不到鼠标指针的修改方式
  14. win10 家庭版升级win11
  15. plc梯形图转c语言,plc梯形图转换成stl程序的实例教程
  16. 嵌入式系统开发笔记0_0:目录
  17. 紫装の槍使い(トゥーヴァ) / 紫枪(异时层土法)
  18. echarts 实现横坐标只显示第一个和最后一个自定义的内容
  19. 大连三家软件企业入围全国软件百强排行榜
  20. Windowns10配置安装Seata14.0(注册中心和配置中心用的都是nacos)

热门文章

  1. 工业电柜空调 工业电柜空调Eco模式 拓展温度冷热板 机架式循环冷却装置 水冷式冷却器 热交换与冷藏 热电冷却 热电冷却器 热电冷板 热电外壳冷却器 热电板冷却器 热电空调 电热冷却台 电热电柜空调
  2. 小白扫盲——双系统装机
  3. win10 中谷歌浏览器安装的插件位置
  4. php中基本符号,PHP中的基本符号及方法
  5. 手把手带你了解时间复杂度和空间复杂度 【超详细】
  6. 游戏蓝牙耳机哪款好?年末盘点:高性价比低延迟蓝牙耳机排名
  7. 新手入门:认识wifi的无线信道
  8. 程序员进阶升级全攻略
  9. seo从入门到精通_SEM必读书单丨从入门到精通,这9本书就是你的钥匙!
  10. SE API第10/11天:集合 ——>ArrayListals、Iterator遍历迭代器、增强for、List集→subList、集合间转换asList、排序sort | Map相关