因为某种需要,需要将在tuleap上的用例导出给外部人员。但是tuleap导出用例时存在以下几种问题:
1、有些用例因为使用的是html文本编辑框输出,所以直接使用内置导出时会带有标签<p></p>等之类的问题,不美观
2、导出的excel文件中无法显示图片等
如:https://www.cnblogs.com/mumu-lin/p/15245384.html 此方案仅能解决标签问题,不能解决展示图片问题,所以考虑使用chm格式来展示用例。
CHM文件可以利用HTML作为源文,在windows 上不需要安装阅读软件就可以打开查看,CHM成了帮助文档、电子书等比较常用的格式。最终效果如下图
因为HTML文件格式可以制作成为CHM文件,所以我们需要考虑下怎么将用例输出为HTML格式:抓包获取每个用例的数据,然后将我们需要的标题、详细内容、图片、模块、子模块提取出来,然后生成html文件
# -*- coding:utf-8 -*- import json import ssl import urllib.request import sys,os import pprint # 控制输出的打印时的缩进,行宽、甚至打印深度 pp = pprint.PrettyPrinter(indent=4) ''' indent 缩进 width 宽度 depth 打印深度 stream 指输出流对象,stream = None输出流对象默认是sys.stdout compact 如果compact为false(默认值),则长序列中的每个项目将在单独的行上进行格式化。如果compact为true,则将在每个输出行上格式化适合宽度的项目。 ''' class TuleapService(object): def __init__(self, *args, **kwargs): self.root = os.getcwd() def getOne(self, code): # python报SSL错误时,取消SSL的证书验证。 ssl._create_default_https_context = ssl._create_unverified_context url = "https://xxx/api/artifacts/" + code try: urllib.request.urlopen(url) headers = {"Content-type": "application/json", "Accept": "application/json", "X-Auth-AccessKey": "t"} paramsDic = {"values": [{"field_id": 2370, "bind_value_ids": []}]} # Python数据结构转换为JSON d = json.dumps(paramsDic).encode(encoding='UTF8') # Request类来构造请求(加入headers等信息),urlopen()方法发起请求 req = urllib.request.Request(url=url, data=d, headers=headers, method='GET') f = urllib.request.urlopen(req) # read()方法读取html的内容(字符内容和链接的形式存在的图片),否则只是一个.urlopen()返回的对象,然后将JSON数据结构转换为PYTHON return json.loads(f.read()) except: return {'tracker': {'label': ''}} if __name__ == "__main__": update = TuleapService() tcs = [] for i in range(25356, 25357): #print(i) tcid = str(i) dict = update.getOne(tcid) tctype = dict['tracker']['label'] if tctype == '测试用例': #desc = getByKey(dict['values'], 761) #print(dict) tcs.append(i) #open('./tcjson/'+tcid+'.txt', 'w', encoding='utf-8').write(str(pp.pformat(dict))) open('./tcjson/'+tcid+'.txt', 'w', encoding='utf-8').write(json.dumps(dict)) # pformat()想获得数据而不是输出数据 open('tcs.json', 'w').write(str(pp.pformat(tcs)))
import json import ssl import shutil import urllib.request import requests import sys,os,os.path from bs4 import BeautifulSoup import pprint pp = pprint.PrettyPrinter(indent=4) class TC2HTML(object): """""" def __init__(self, *args, **kwargs): self.root = os.getcwd() def loadFromFile(self, code): ''' 读取生成的txt文件 :param code: :return: ''' fname = './tcjson/' + str(code) + '.txt' if os.path.isfile(fname): data = open(fname, 'r', encoding='utf-8').read() data = json.loads(data) #print( str(pp.pformat(data)) ) return data else: return def getByKey(self, fields, id): for d in fields: if d['field_id']==id: return d['value'] def getById(self, fields, id): # 判断用例ID是否存在 for d in fields: if d['field_id']==id: return d return def downloadImg(self, code): self.tcCode = code dict = self.loadFromFile(code) if not dict: return print(code) #用例脚本id bodyField = self.getById(dict['values'], 761) if not bodyField: bodyField = self.getById(dict['values'], 2920) body = bodyField['value'] if bodyField['format'] == 'text': return bs = BeautifulSoup(body, 'html.parser') bs = bs.find_all('img') #print(bs) for it in bs: self.fetchImg(code, it['src']) def mkdir(self, path): # 创建文件夹 path = path.strip() is_exists = os.path.exists(path) if not is_exists: os.makedirs(path) def fetchImg(self, code, src): if not src.startswith('/upload/'): print('特殊路径图片') return url = 'https://172.17.189.54%s' % src print(src) headers = { # 给请求指定一个请求头来模拟chrome浏览器 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64)' ' AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'} name = src.split('/')[2] fpth = './imgs/'+code+'/upload' if os.path.isfile('./imgs/'+code+src): print('图片已存在') return self.mkdir(fpth) os.chdir(fpth) ssl._create_default_https_context = ssl._create_unverified_context urllib.request.urlopen(url) headers = {"Content-type": "image/png", #"Accept": "application/json", "X-Auth-AccessKey": "t"} req = urllib.request.Request(url=url, data={}, headers=headers, method='GET') f = urllib.request.urlopen(req) imgFile = open(name, 'ab') imgFile.write(f.read()) imgFile.close() os.chdir('../../../') if __name__ == "__main__": update = TC2HTML() for i in range(115, 34000): update.downloadImg(str(i))
# -*- coding:utf-8 -*- import json import ssl import shutil import urllib.request import requests import sys,os,os.path from bs4 import BeautifulSoup import pprint pp = pprint.PrettyPrinter(indent=4) HTML_TMPL = '''<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-16" /> <title>{title}</title> <body> <div> <h3>{title}</h3> <div class="tc-body"> {body} <div> <div> </body> </head> </html>''' PASS_ID = 894 FAIL_ID = 895 class TC2HTML(object): def setCode(self, code): ''' 根据字段id,读取每个用例对应txt文件内的标题,父模块、子模块 :param code: :return: ''' self.tcCode = code dict = self.loadFromFile(code) if not dict: return print(code) #标题 title = self.getByKey(dict['values'], 768) if not title: title = self.getByKey(dict['values'], 2926) #用例脚本 bodyField = self.getById(dict['values'], 761) if not bodyField: bodyField = self.getById(dict['values'], 2920) #父模块 parentCatField = self.getById(dict['values'], 2576) pCatName = None dirName = './dirs/其他/' if not os.path.exists(dirName): os.makedirs(dirName) if parentCatField and len(parentCatField['values']) > 0: # 根据创建父模块的目录 pCatName = parentCatField['values'][0]['label'] dirName = './dirs/' +pCatName+'/' if not os.path.exists(dirName): print(pCatName) os.makedirs(dirName) #子模块 childCatField = self.getById(dict['values'], 2577) cCatName = None if childCatField and len(childCatField['values']) > 0: #print(childCatField) cCatName = childCatField['values'][0]['label'] if pCatName: dirName = './dirs/' +pCatName+'/'+cCatName+'/' print(dirName) if not os.path.exists(dirName): os.makedirs(dirName) body = bodyField['value'] if bodyField['format'] == 'text': body = '<br />'.join(body.split("\n")) else: # 在body中添加图片路径 body = '<img src="./upload/'.join(body.split('<img src="/upload/')) #拷贝图片 print(dirName) uploadFolder = dirName+'/upload/' if not os.path.exists(uploadFolder): os.makedirs(uploadFolder) source_dir = "./imgs/" +code+ '/upload/' destination_dir = uploadFolder if os.path.exists(source_dir): print(os.listdir(source_dir)) for it in os.listdir(source_dir): shutil.copy(source_dir+it, destination_dir+it) params = { 'title': title, 'body': body } # 将替换大括号内容的数据写入到html文件中 open(dirName+code+'.html', 'w', encoding='UTF-16').write(HTML_TMPL.format(**params) ) def loadFromFile(self, code): # 读取txt文件 fname = './tcjson/' + str(code) + '.txt' if os.path.isfile(fname): data = open(fname, 'r', encoding='utf-8').read() data = json.loads(data) #print( str(pp.pformat(data)) ) return data else: return def getByKey(self, fields, id): for d in fields: if d['field_id']==id: return d['value'] def getById(self, fields, id): for d in fields: if d['field_id']==id: return d return def mkdir(self, path): # 创建文件夹 path = path.strip() is_exists = os.path.exists(path) if not is_exists: os.makedirs(path) if __name__ == "__main__": update = TC2HTML() for i in range(115, 34000): update.setCode(str(i))
可以使用WINCHM将html文件生成CHM:
可参考以下链接
https://jingyan.baidu.com/article/4f7d5712c9b2041a201927c8.html