xmind2testcase安装、简单二次开发与使用说明:
添加xmind文件备份
重构生成CSV文件
preview预览页面数据显示重构
一、安装
1.xmind2testcase安装
pip install xmind2testcase
2.启动服务
进入默认位置:C:\Users\dell\AppData\Roaming\Python\Python38\Scripts,打开cmd命令窗口,执行命令xmind2testcase.exe webtool 5000,浏览器地址栏输入http://本地ip:5000 访问
二、二次开发
源码地址C:\Users\dell\AppData\Roaming\Python\Python38\site-packages\webtool
1.xmind文件备份
打开application.py,添加BACKUP_FOLDER = os.path.join(here, 'backup')
init()方法添加
if not exists(BACKUP_FOLDER):os.mkdir(BACKUP_FOLDER)
save_file(file)添加
shutil.copy(upload_to, BACKUP_FOLDER)
2.重构生成CSV脚本
import xlwt
from xmindparser import xmind_to_dict
import os'''
对xmind文件增加了多种样式的处理
'''def font():'''设置字体:return:'''font = xlwt.Font()font.bold = Falsereturn fontdef border():'''设置边框:return:'''border = xlwt.Borders()border.left = 1border.right = 1border.top = 1border.bottom = 1return borderdef backcolor():'''设置背景色:return:'''backcolor = xlwt.Pattern()backcolor.pattern = xlwt.Pattern.SOLID_PATTERNbackcolor.pattern_fore_colour = 21return backcolordef style():'''设置不同样式:return:'''# 设置第一行样式alignment0 = xlwt.Alignment()alignment0.horz = 0x02alignment0.vert = 0x01style0 = xlwt.XFStyle()style0.alignment = alignment0style0.borders = border()style0.font = font()style0.pattern = backcolor()# 用例编码、模块样式alignment1 = xlwt.Alignment()alignment1.horz = 0x02alignment1.vert = 0x01style1 = xlwt.XFStyle()style1.alignment = alignment1# 测试用例名称样式alignment2 = xlwt.Alignment()alignment2.horz = 0x01alignment2.vert = 0x01alignment2.wrap = 1style2 = xlwt.XFStyle()style2.alignment = alignment2# 操作步骤样式alignment3 = xlwt.Alignment()alignment3.horz = 0x01alignment3.vert = 0x01alignment3.wrap = 1 # 单元格内自动换行style3 = xlwt.XFStyle()style3.alignment = alignment3style3.alignment.wrap = 1 # 单元格有换行符时换行# 预期结果样式alignment4 = xlwt.Alignment()alignment4.horz = 0x01alignment4.vert = 0x01alignment4.wrap = 1style4 = xlwt.XFStyle()style4.alignment = alignment4return style0, style1, style2, style3, style4class xmind_to_csv():""" xmind文档用例转xls文档用例"""def infinite_for(self, loop, case, case_list, n):for branches in loop:# 定义新字符串,把所有路径加起来strvar = case + branches['title'] + '/#'if 'topics' not in branches:# 分支遍历完,把他加到列表里面case_list.append(strvar)continuebranch = branches['topics']# 无限循环调用方法,遍历他的全部分支self.infinite_for(branch, strvar, case_list, n)# 根据传参重写路径# else:# strvar = strvardef read_xmind(self, filename):if filename.endswith('.xmind') and os.path.exists(filename):self.xmind = xmind_to_dict(filename)self.file_name = filename.split('.')[0]return self.xmind, self.file_nameelse:print('文件格式不对或文件不存在!')def write_excel(self, filename):'''生成excel文件函数'''global li_varstyles = style() # xls单元格样式self.workbook = xlwt.Workbook(encoding='utf-8')self.worksheet = self.workbook.add_sheet('sheet1', cell_overwrite_ok=True)row_0 = ['用例编码', '模块', '测试要点', '测试用例标题', '操作步骤', '预期结果', '实际结果', '是否通过','执行人员', '备注']sizes = [10, 15, 30, 30, 50, 30, 30, 10, 10, 30] # 设置单元格长度for i in range(len(row_0)):self.worksheet.write(0, i, row_0[i], styles[0])self.worksheet.col(i).width = sizes[i] * 256 # 设置单元格长度self.worksheet.row(0).height_mismatch = True # 设置单元格高度self.worksheet.row(0).height = 4 * 256self.worksheet.set_panes_frozen('1') # 设置冻结为真self.worksheet.set_horz_split_pos(1) # 水平冻结第一行self.worksheet.set_vert_split_pos(2) # 垂直冻结第一列# 开始解析xmind并写入excelself.xd = self.read_xmind(filename)self.xls_name = self.xd[0][0]['topic']['title']case_list = [] # 所有用例case = '' # 单条用例self.data_case = self.xd[0][0]['topic']['topics']# 循环遍历整个字典,并把每个最小分支的路径按 /# 加入到case_list 列表中self.infinite_for(self.data_case, case, case_list, 0)try:# print(listvar)n = 1for a_var in case_list:l_var = a_var.split('/#')[:-1]print(l_var)if len(l_var) < 3:# print('格式不符合要求')continueelif len(l_var) == 5:Test_no = '%03d' % n # 用例编号Module = f'{l_var[0]}' # 所属模块Test_point = f'{l_var[1]}' # 测试要点Test_title = f'{l_var[2]}' # 测试标题Test_step = f'{l_var[-2]}' # 操作步骤Test_result = f'{l_var[-1]}' # 预期结果# 写入的参数li_var = [Test_no, Module, Test_point, Test_title, Test_step, Test_result]elif len(l_var) == 4:Test_no = '%03d' % n # 用例编号Module = f'{l_var[0]}' # 所属模块Test_point = f'{l_var[1]}' # 测试要点Test_title = f'{l_var[1]}' # 测试标题Test_step = f'{l_var[-2]}' # 操作步骤Test_result = f'{l_var[-1]}' # 预期结果li_var = [Test_no, Module, Test_point, Test_title, Test_step, Test_result]elif len(l_var) == 3:Test_no = '%03d' % n # 用例编号Module = f'{l_var[0]}' # 所属模块Test_point = f'{l_var[0]}' # 测试要点Test_title = f'{l_var[0]}' # 测试标题Test_step = f'{l_var[-2]}' # 操作步骤Test_result = f'{l_var[-1]}' # 预期结果li_var = [Test_no, Module, Test_point, Test_title, Test_step, Test_result]else:Test_no = '%03d' % n # 用例编号Module = f'{l_var[0]}' # 所属模块Test_point = f'{l_var[1]}' # 测试要点Test_title = f'{l_var[2]}' # 测试标题Test_step = f'{l_var[-2]}' # 操作步骤Test_result = f'{l_var[-1]}' # 预期结果li_var = [Test_no, Module, Test_point, Test_title, Test_step, Test_result]# for j in li_var:# self.worksheet.write(n, int(j[-1]), j[:-1])for i in range(len(li_var)):self.worksheet.write(n, 0, li_var[0], styles[1])self.worksheet.write(n, 1, li_var[1], styles[1])self.worksheet.write(n, 2, li_var[2], styles[2])self.worksheet.write(n, 3, li_var[3], styles[2])self.worksheet.write(n, 4, li_var[4], styles[3])self.worksheet.write(n, 5, li_var[5], styles[3])n += 1self.workbook.save(self.xd[1] + '.csv') # xls名称取xmind主题名称except Exception as e:print(e)if __name__ == '__main__':run = xmind_to_csv()run.write_excel(filename='系统消息001.xmind')# os.system('pause')
download_zentao_file(filename)方法修改,引用新的处理方法,注释原部分代码,使用新的处理方法
#使用重构生成CSV脚本
xmind_csv_file = xmind_to_csv()
xmind_csv_file.write_excel(full_path)
filename=filename.split('.')[0]+'.csv'
if not exists(join(app.config['UPLOAD_FOLDER'], filename)):abort(404)
@app.route('/<filename>/to/zentao')
def download_zentao_file(filename):full_path = join(app.config['UPLOAD_FOLDER'], filename)if not exists(full_path):abort(404)# zentao_csv_file = xmind_to_zentao_csv_file(full_path)# filename = os.path.basename(zentao_csv_file) if zentao_csv_file else abort(404)# return send_from_directory(app.config['UPLOAD_FOLDER'], filename, as_attachment=True)#使用重构生成CSV脚本xmind_csv_file = xmind_to_csv()xmind_csv_file.write_excel(full_path)filename=filename.split('.')[0]+'.csv'if not exists(join(app.config['UPLOAD_FOLDER'], filename)):abort(404)return send_from_directory(app.config['UPLOAD_FOLDER'], filename, as_attachment=True)
3.预览页面重构
预览数据处理
import xlwt
from xmindparser import xmind_to_dict
import osdef read_xmind(filename):'''读取xmind文件:param filename: xmind文件名'''if filename.endswith('.xmind') and os.path.exists(filename):xmind = xmind_to_dict(filename)return xmindelse:print('文件格式不对或文件不存在!')def infinite_for(loop, case, TestCase_lise, n):for branches in loop:# 定义新字符串,把所有路径加起来strvar = case + branches['title'] + '/#'if 'topics' not in branches:# 分支遍历完,把他加到列表里面TestCase_lise.append(strvar)continuebranch = branches['topics']# 无限循环调用方法,遍历他的全部分支infinite_for(branch, strvar, TestCase_lise, n)# return TestCase_lisedef do_xmind(filename):'''处理xmind文件,数据将显示在preview预览页面'''TestCase_lise = []suite = read_xmind(filename)# print(suite)suite_name = suite[0]['topic']['title']case_list = [] # 所有用例case = '' # 单条用例data_case = suite[0]['topic']['topics']infinite_for(data_case, case, case_list, 0)# print(case_list)# print(len(case_list))for i in case_list:i=i.split('/#')[:-1]TestCase_lise.append(i)print(TestCase_lise)return TestCase_liseif __name__ == '__main__':do_xmind('系统消息001.xmind')
application.py引入模块
preview_file(filename)方法修改,注释旧代码,引入新处理方法
# testcases = get_xmind_testcase_list(full_path)
#重写界面显示数据
testcases=do_xmind(full_path)
@app.route('/preview/<filename>')
def preview_file(filename):full_path = join(app.config['UPLOAD_FOLDER'], filename)if not exists(full_path):abort(404)testsuites = get_xmind_testsuites(full_path)suite_count = 0for suite in testsuites:suite_count += len(suite.sub_suites)# testcases = get_xmind_testcase_list(full_path)#重写界面显示数据testcases=do_xmind(full_path)return render_template('preview.html', name=filename, suite=testcases, suite_count=suite_count)
preview.html修改
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>{{ name }} | Xmind2TestCase Preview</title><link rel="shortcut icon" href="{{ url_for('static',filename='favicon.ico') }}" type="image/x-icon"/><link rel="stylesheet" type="text/css" media="all" href="{{ url_for('static',filename='css/pure-min.css') }}"><link rel="stylesheet" type="text/css" media="all" href="{{ url_for('static',filename='css/custom.css') }}">
</head>
<body>
<div class="header"><h1>{{ name }}</h1><h2>用例模块: {{ suite_count }} / 用例数量: {{ suite | length }}/ <a href="{{ url_for("download_zentao_file",filename= name) }}">下载CSV</a>/ <a href="{{ url_for("download_testlink_file",filename= name) }}">下载XML</a>/ <a href="{{ url_for("index") }}">返回首页</a></h2>
</div>
<table class="pure-table tests-table"><thead><tr><th width="5%">序号</th><th width="10%">模块</th><th>测试要点</th><th width="40%">操作步骤</th><th width="23%">预期结果</th></tr></thead><tbody>
{# {% for test in suite %}#}
{# <tr>#}
{# <td>{{ loop.index }}</td>#}
{# <td>{{ test.suite }}</td>#}
{# <td {% if test.name|length>100 %}class="long-name" {% endif %}>{{ test.name }}#}
{# {% if test.name|length>100 %}#}
{# <span class="long-name-info">Warn: test name might be too long: {{ test.name|length }}!</span>#}
{# {% endif %}#}
{# </td>#}
{# <td>#}
{# <div class="tag-success tooltip">#}
{# Priority {{ test.importance }}#}
{# <span class="tooltiptext">Priority {{ test.importance }} </span>#}
{# </div>#}
{# {% if test.preconditions %}#}
{# <div class="pure-button tag-info tooltip">PreCond.#}
{# <p class="tooltiptext">#}
{# <b>Preconditions:</b> <br>#}
{# {{ test.preconditions | replace('\n','<br>') |safe }}#}
{# </p></div>#}
{# {% endif %}#}
{# {% if test.summary %}#}
{# <div class="pure-button tag-warn tooltip">Summary#}
{# <p class="tooltiptext">#}
{# <b>Summary:</b> <br>#}
{# {{ test.summary | replace('\n','<br>') |safe }}#}
{# </p></div>#}
{# {% endif %}#}
{# <td>#}
{# {% if test.steps %}#}
{# <ol>#}
{# {% for step in test.steps %}#}
{# <li>{{ step.actions }}#}
{# {% if step.expectedresults %}#}
{# <ul>#}
{# <li>{{ step.expectedresults }}</li>#}
{# </ul>#}
{# {% endif %}#}
{# </li>#}
{# {% endfor %}#}
{# </ol>#}
{# {% endif %}#}
{# </td>#}
{# </tr>#}
{# {% endfor %}#}{% for test in suite %}<tr><td>{{ loop.index }}</td><td>{{ test[0] }}</td>{% if test|length>2 %}<td>{{ test[-3] }}</td>{% else %}<td>{{ test[0] }}</td>{% endif %}<td>{{ test[-2] }}<td>{{ test[-1] }}</td></tr>{% endfor %}</tbody>
</table>
{#<div class="footer">#}
{# <a href="{{ url_for('static', filename='guide/index.html') }}" target="_blank">User Guide</a> |#}
{# <a href="https://github.com/zhuifengshen/xmind2testcase/issues/new" target="_blank">Report Issue</a> |#}
{# Powered by <a href="https://github.com/zhuifengshen/xmind2testcase" target="_blank">XMind2TestCase</a>#}
{#</div>#}
</body>
</html>
效果: