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 = False
return font
def border():
'''
设置边框
:return:
'''
border = xlwt.Borders()
border.left = 1
border.right = 1
border.top = 1
border.bottom = 1
return border
def backcolor():
'''
设置背景色
:return:
'''
backcolor = xlwt.Pattern()
backcolor.pattern = xlwt.Pattern.SOLID_PATTERN
backcolor.pattern_fore_colour = 21
return backcolor
def style():
'''
设置不同样式
:return:
'''
# 设置第一行样式
alignment0 = xlwt.Alignment()
alignment0.horz = 0x02
alignment0.vert = 0x01
style0 = xlwt.XFStyle()
style0.alignment = alignment0
style0.borders = border()
style0.font = font()
style0.pattern = backcolor()
# 用例编码、模块样式
alignment1 = xlwt.Alignment()
alignment1.horz = 0x02
alignment1.vert = 0x01
style1 = xlwt.XFStyle()
style1.alignment = alignment1
# 测试用例名称样式
alignment2 = xlwt.Alignment()
alignment2.horz = 0x01
alignment2.vert = 0x01
alignment2.wrap = 1
style2 = xlwt.XFStyle()
style2.alignment = alignment2
# 操作步骤样式
alignment3 = xlwt.Alignment()
alignment3.horz = 0x01
alignment3.vert = 0x01
alignment3.wrap = 1 # 单元格内自动换行
style3 = xlwt.XFStyle()
style3.alignment = alignment3
style3.alignment.wrap = 1 # 单元格有换行符时换行
# 预期结果样式
alignment4 = xlwt.Alignment()
alignment4.horz = 0x01
alignment4.vert = 0x01
alignment4.wrap = 1
style4 = xlwt.XFStyle()
style4.alignment = alignment4
return style0, style1, style2, style3, style4
class 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)
continue
branch = branches['topics']
# 无限循环调用方法,遍历他的全部分支
self.infinite_for(branch, strvar, case_list, n)
# 根据传参重写路径
# else:
# strvar = strvar
def 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_name
else:
print('文件格式不对或文件不存在!')
def write_excel(self, filename):
'''生成excel文件函数'''
global li_var
styles = 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 * 256
self.worksheet.set_panes_frozen('1') # 设置冻结为真
self.worksheet.set_horz_split_pos(1) # 水平冻结第一行
self.worksheet.set_vert_split_pos(2) # 垂直冻结第一列
# 开始解析xmind并写入excel
self.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 = 1
for a_var in case_list:
l_var = a_var.split('/#')[:-1]
print(l_var)
if len(l_var) < 3:
# print('格式不符合要求')
continue
elif 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 += 1
self.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 os
def read_xmind(filename):
'''
读取xmind文件
:param filename: xmind文件名
'''
if filename.endswith('.xmind') and os.path.exists(filename):
xmind = xmind_to_dict(filename)
return xmind
else:
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)
continue
branch = branches['topics']
# 无限循环调用方法,遍历他的全部分支
infinite_for(branch, strvar, TestCase_lise, n)
# return TestCase_lise
def 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_lise
if __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 = 0
for 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>
效果: