一直以来都喜欢用思维导图的方式去写用例,或者记录一些要做的任务。逻辑清晰,分工明确,提高我们的工作效率。但如果任务细化到一定程度,思维导图的展示会难看,放大了看不清逻辑关系,缩小了又看不清具体描述。自己python脚本,及reactjs前端技术,写了这个转换方法。
先简单说下我的工作步骤:
1.Xmind,编写用例,导出为html文件。
2.上传到后台服务端放导指定位置。
3.前台发起请求后台处理上传的文件并格式化返回,前台展示数据。
我一般都是写的逻辑向右的导图,首先我们把xmind的用例导出为html,导出页面上不要勾选任何选项。例如我的导出文件为test.html。
虽然导出的已经html了,但毫无格式可言,看起来是很吃力的。
通过脚本提取其中有用数据,并给它们每条一个id编号。
1 2 3 4 5 6 7 8
| file = open('app/static/uploads/test1.html').read() soup = BeautifulSoup(file) allData = [] count = 1 for k in soup.find_all('a'): value = k.text.replace(u'\xa0', u'$') allData.append([count, value]) count += 1
|
这里看到‘replace(u’\xa0’, u’$’)’需要说明下,导出的数据他们的父子关系主要是靠空格来区分,这里\xa0就是空格,方便后面数据转换,我把它们替换成了’$’,所以可以说,我们的导图文本里不能写这个关键字,不然会有错误。
下面就是给它们理清楚出父子关系了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| sz = [] allData[0].append(0) allData[1].append(0) sz.append(allData[0]) sz.append(allData[1]) for i in range(len(allData)): if i > 1: prew_index = len(allData[i - 1][1]) - len(allData[i - 1][1].replace('$', '')) now_index = len(allData[i][1]) - len(allData[i][1].replace('$', '')) if now_index - prew_index == 1: allData[i].append(allData[i - 1][0]) elif now_index - prew_index == 0: try: allData[i].append(allData[i - 1][2]) except: print allData[i - 1] elif now_index - prew_index < 0: for l in range(0, len(sz)): _prew_index = len(sz[(len(sz) - 1) - l][1]) - len(sz[(len(sz) - 1) - l][1].replace('$', '')) if now_index - _prew_index == 0: allData[i].append(sz[(len(sz) - 1) - l][2]) break sz.append(allData[i])
|
获取到的sz数组,就是当前导出的数据格式化数据了,每条数据都有个自己的id,名字,父id。但我的reactjs前端页面需要的是,有子集的树形结构数据。
通过下面的遍历方法把数据再次格式化处理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| def getchild(pid): result = [] for obj in sz: if obj[2] == pid: result.append({ "id": obj[0], "title": obj[1].replace('$',''), "pid": obj[2], "children": getchild(obj[0]), })
return result
newResult = getchild(0) for item in range(1, len(newResult)): newResult[0]["children"].append(newResult[item]) for item in range(1,len(newResult)): newResult.pop()
|
到这里,数据处理的核心部分已经完成了。但要给前端页面展示,我还要把脚本封装到服务端,并通过接口传给前端页面。
我用的flask,提供restful接口。
前端部分用的是react框架,主要是用antd的ui库:
核心部分如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| class CaseList extends React.Component{ state = { fetch_data:[], ...
} fetchList=()=>{ var par = "entry=0" fetch('http://192.168.1.101:5000/gettasklist',{ method: "POST", mode: "cors", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: par })... } render(){ const { fetch_data} = this.state; const columns = [ { title: 'title', dataIndex: 'title', key: 'title', render: text => <a style={{marginLeft:30,fontSize:16}}>{text}</a>, }]; return( <Page title="case列表" loading={this.state.isLoading}> <Table rowKey="id" columns={columns} dataSource={fetch_data} indentSize={50}/> </Page> ); } }
|
实际使用时,我是通过一个上传页面直接上传导出文件到服务器的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <Page title="上传导出文件" loading={this.state.isLoading}> <div style={{alignItems:'center', justifyContent:"center",display:'flex',flex:1, flexDirection:'column', marginTop:"20%"}}> <Upload {...props}> <Button> <Icon type="upload" /> Select File </Button> </Upload> <Button className="upload-demo-start" type="primary" onClick={this.handleUpload} disabled={this.state.fileList.length === 0} loading={uploading} style={{marginTop:20}} > {uploading ? 'Uploading' : 'Start Upload' } </Button> </div> </Page>
|
后续还将优化前端和脚本生成的数据,通过写入数据库,前端可以执行测试通过、已完成等,以记录我们的测试点的执行状态。前端部分感兴趣的可以看下我的源码:https://github.com/t880216t/manager-web