一、圖標說明
二、效果
xmind備注
【前置條件】
【操作步驟】
【SQL校驗】
【預期結果】
【備注】
三、解析XMind
備注:已封裝好 可直接調用
JarExcelUtil工具類:https://www.cnblogs.com/danhuai/p/13538291.html
Xmind版本:XMind 8
""" -*- coding:utf-8 -*- @Time :2020/9/4 15:07 @Author :維斯 @File :jar_xmind_util.py @Version:1.0 """ import json import xmind from common.jar_excel_util import JarExcelUtil class JarXmindUtil: def __init__(self): # markers字段 "markers": ["star-orange"] self.model = ['star-dark-gray', '$所屬模塊$'] # [所屬模塊(灰色星星標志),標識] self.check = ['star-orange', '$驗證點$'] # [驗證點(黃色星星標志),標識] self.except_case = ['people-red', '$異常$'] # [異常用例(紅色人像標志),標識] self.normal_case = ['people-green', '$正常$'] # [正常用例(綠色人像標志),標識] self.priority_1 = ['priority-1', '$高$'] # [重要級別-高(1號優先級標志),標識] self.priority_2 = ['priority-2', '$中$'] # [重要級別-中(2號優先級標志),標識] self.priority_3 = ['priority-3', '$低$'] # [重要級別-低(3號優先級標志),標識] # 匯總 self.all_markers = [self.model, self.check, self.except_case, self.normal_case, self.priority_1, self.priority_2, self.priority_3 ] self.note = ['note', '$備注節點$'] self.comment = ['comment', '$批注節點$'] # 節點分割符 self.node_split = ' /' # 節點分割符 self.node_split_excel = ' /' # 寫入表格中的多節點分割符 # 預期結果分割符 self.node_expect_split = '預期結果:' # 用例編號前綴 self.case_number_model = 'CASE_200917' # 生成的用例編號 如 CASE_200917000001、CASE_200917000002 # Xmind備注信息模板解析(嚴格按照此順序解析) self.xmind_note_model = [['【前置條件】', '內容'], ['【操作步驟】', '內容'], ['【SQL校驗】', '內容'], ['【預期結果】', '內容'], ['【備注】', '內容']] # 測試用例表格 self.headers = [ ['用例編號', len(self.case_number_model) + 5 + 5], # 長度多5個字符 ['用例類型'], ['重要級別'], ['所屬模塊', 20], ['驗證點', 20], ['用例標題', 60], ['前置條件', 12], ['操作步驟', 12], ['SQL校驗', 12], ['預期結果', 12], ['備注', 12] ] @staticmethod def del_endswith_none(str1: str): """ 刪除字符串首尾的空字符(空格、換行) :param str1: """ s = str1 if str1 is not None: while True: if s.endswith(' ') or s.endswith(' ') or s.endswith('\r\n') or s.endswith('\r') or s.endswith('\n'): s = s[:-1] elif s.startswith(' ') or s.startswith(' ') or s.startswith('\r\n') or s.startswith( '\r') or s.startswith('\n'): s = s[1:] else: break return s def to_excel(self, out_file, result_node: list): """ 解析的Xmind數據寫入表格文件 :param out_file: 表格文件 :param result_node: 列表 每一個元素為一個完整的xmind路徑 """ body_data = [] count = 0 for re in result_node: count += 1 # 1 分割某鏈路所有節點 node_list = re.split(self.node_split) # 2 判斷節點屬性 re_model = '' # 所屬模塊 re_check = '' # 驗證點 re_case_type = '' # 用例類型 re_case_name = '' # 用例標題 re_priority = '' # 重要級別 re_expect = '' # 預期結果 re_note = '' # 備注(xmind中的備注) re_comment = '' # 批注(xmind中的批注) for n in node_list: n: str # 2.1 所屬模塊 if n.startswith(self.model[1]): re_model += n.replace(self.model[1], '') + self.node_split_excel # 2.3 驗證點 if n.startswith(self.check[1]): re_check += n.replace(self.check[1], '') + self.node_split_excel # 2.4 用例類型&用例標題 if n.startswith(self.except_case[1]) or n.startswith(self.normal_case[1]): if n.startswith(self.except_case[1]): re_case_type = self.except_case[1][1:-1] re_case_type_swap1 = n.split(self.except_case[1]) if re_case_type_swap1 == 3: re_case_name += re_case_type_swap1[1] + self.node_split_excel else: re_case_name += n.replace(self.except_case[1], '') + self.node_split_excel if n.startswith(self.normal_case[1]): re_case_type = self.normal_case[1][1:-1] re_case_type_swap2 = n.split(self.normal_case[1]) if re_case_type_swap2 == 3: re_case_name += re_case_type_swap2[1] + self.node_split_excel else: re_case_name += n.replace(self.normal_case[1], '') + self.node_split_excel # 2.5 重要級別 if n.startswith(self.priority_1[1]): re_priority = self.priority_1[1][1:-1] if n.startswith(self.priority_2[1]): re_priority = self.priority_2[1][1:-1] if n.startswith(self.priority_3[1]): re_priority = self.priority_3[1][1:-1] # 2.6 預期結果 re_expect = n[n.find(self.node_expect_split):] re_expect = re_expect[len(self.node_expect_split):] re_expect = self.del_endswith_none(re_expect) # 2.7 備注 re_note_swap = n.split(self.note[1]) if len(re_note_swap) == 3: re_note = re_note_swap[1] # 2.8 批注 re_comment_swap = n.split(self.comment[1]) if len(re_comment_swap) == 3: re_comment = re_comment_swap[1] # 刪除末尾的分割符 length = len(self.node_split_excel) re_model = re_model[:len(re_model) - length] re_check = re_check[:len(re_check) - length] re_case_name = re_case_name[:len(re_case_name) - length] # 刪除用例名稱后的 預期結果、空格、換行 index = re_case_name.find(self.node_expect_split) re_case_name = re_case_name[:None if index == -1 else index] re_case_name = self.del_endswith_none(re_case_name) # 解析XMind中的備注信息 for n in range(len(self.xmind_note_model)): # 提取名稱(如:【前置條件】 提取為 前置條件) 分別去除前后1個字符 n_name = self.xmind_note_model[n][1:-1] # 提取此名稱下的數據(如:提取哪些內容是前置條件) 截取XMind中備注信息中 n至n+1中的數據 if n < len(self.xmind_note_model) - 1: n_data = re_note[ re_note.find(self.xmind_note_model[n][0]):re_note.find(self.xmind_note_model[n + 1][0])] else: n_data = re_note[re_note.find(self.xmind_note_model[n][0]):] n_data = n_data[len(self.xmind_note_model[n][0]):] n_data = self.del_endswith_none(n_data) self.xmind_note_model[n][1] = n_data # 3 拼接節點至指定表格字段 body = [ self.case_number_model + str(count).zfill(6), # 用例編號 re_case_type, # 用例類型 re_priority, # 重要級別 re_model, # 所屬模塊 re_check, # 驗證點 re_case_name, # 用例標題 self.xmind_note_model[0][1], # 前置條件 self.xmind_note_model[1][1], # 操作步驟 self.xmind_note_model[2][1], # SQL校驗 self.xmind_note_model[3][1], # 預期結果 self.xmind_note_model[4][1] # 備注 ] body_data.append(body) JarExcelUtil(header_list=self.headers).write(out_file=out_file, data_body=body_data) print('數據寫入Excel完成!(路徑:{})'.format(out_file)) @staticmethod def analysis(xmind_path): """ 解析Xmind文件(獲取每條完整路徑) :param xmind_path: xmind文件 :return: 返回所有路徑list """ wb = xmind.load(xmind_path) data = wb.to_prettify_json() data = json.loads(data) result_data = [] # 畫布 for data_topic in data: # 1級 data_1 = data_topic.get('topic') title_1 = data_1.get('title') # 遞歸后面所有級(2級、3級、......) JarXmindUtil().__base(title_1, data_1, result_data) print('{},xmind數據解析完成!'.format(xmind_path)) # print(*result_data, sep='\n') return result_data def __base(self, title_long_x, data_topics_x, result_data_all): """ 遞歸Xmind所有子標題 :param title_long_x: :param data_topics_x: :param result_data_all: """ # 遞歸所有級 topics_list = data_topics_x.get('topics') for topics in topics_list: # 循環所有路徑 title = '' swap = '' # 取節點圖標屬性 markers: list = topics.get('markers') if len(markers) != 0: for marker in markers: # 循環該節點所有屬性 for all_mar in self.all_markers: # 循環預定所有屬性值 if marker == all_mar[0]: # 節點markers屬性中有預定值 # 若是用例名稱節點 則獲取備注與批注信息 if marker == self.all_markers[2][0] or marker == self.all_markers[3][0]: # 綠色人像或紅色人像 # 是用例節點 s_note = topics.get('note') if topics.get('note') is not None else '' s_comment = topics.get('comment') if topics.get('comment') is not None else '' title = '{}{}{}{}{}'.format(title_long_x + swap, self.node_split, all_mar[1] + topics.get('title') + all_mar[1] + self.node_split, self.note[1] + str(s_note) + self.note[1] + self.node_split, # 備注 self.comment[1] + str(s_comment) + self.comment[ 1] + self.node_split) # 批注 swap = self.node_split + all_mar[1] + topics.get('title') + all_mar[ 1] + self.node_split + self.note[ 1] + str(s_note) + self.note[1] + self.node_split + self.comment[ 1] + str(s_comment) + self.comment[1] else: # 非用例節點 title = '{}{}{}'.format(title_long_x + swap, self.node_split, all_mar[1] + topics.get('title') + all_mar[1] + self.node_split) swap = self.node_split + all_mar[1] + topics.get('title') + all_mar[1] break else: # 循環到最后 沒匹配到(說明此標志沒有在預定標志中) if markers[len(markers) - 1] == marker \ and self.all_markers[len(self.all_markers) - 1] == all_mar: print('節點:【{}】,在預定標志中未匹配到此標志({})'.format(topics.get('title'), marker)) else: title = '{}{}{}'.format(title_long_x, self.node_split, topics.get('title')) # 取節點值 if topics.get('topics') is not None: JarXmindUtil().__base(title, topics, result_data_all) else: result_data_all.append(title) continue if __name__ == '__main__': ju = JarXmindUtil() # XMind文件 path = 'E:\\xxx項目測試用例.xmind' # 用例編號前綴 ju.case_number_model = 'CASE_201101' # step1 解析xmind result = ju.analysis(path) # step2 寫入excel ju.to_excel('xxx項目測試用例.xlsx', result)