標籤:lib http 時間 turn 資訊 比較 初始 eve count
背景
百科上說TestLink 是基於web的測試案例管理系統,主要功能是測試案例的建立、管理和執行,並且還提供了一些簡單的統計功能。其他的資訊可以參照他們的官網http://www.testlink.org/
。
樓主所在的項目,需求、提測、測試等等都是使用的是gitlab的一個個issue加標籤管理的,用例的維護在開始的時候也是用的它。後來我們的直接上級職位發生了變更,新leader建議我們使用testlink。
試用了一段時間之後,發現一個非常令人詬病的地方--用例匯入只支援xml格式,而且它本身的用例編寫也不太方便。
這也是我寫這個用例匯入小工具的初衷。
思路
開始時博主想的是,把Excel編寫的用例(Excel應該是所有測試人員編寫用例的首選吧)轉換為xml格式匯入,後來發現更好的辦法-封裝Python testlink API。
寫得比較倉促,還有很多可以改進的地方,先用起來,後續最佳化。
具體實現環境依賴
環境依賴 |
安裝方法 |
Python3 |
略 |
xlrd庫 |
pip install xlrd |
testlink庫 |
pip install TestLink-API-Python-client |
目錄結構
目錄結構如下,testCase目錄用於存放測試案例,upload_excel_data.py用於用例轉換上傳,logger_better.py用於記錄日誌,。
D:\PROJECT\UPLOAD_DATA2TESTLIN│ logger_better.py│ upload_excel_data.py│└─testCase testCase_Example.xlsx
使用方法
upload內容
#! /usr/bin/python# coding:utf-8 """ @author:Bingo.he @file: upload_excel_data.py @time: 2018/05/03 """import collectionsimport testlinkimport xlrdimport osfrom logger_better import Loglogger = Log(os.path.basename(__file__))count_success = 0count_fail = 0def get_projects_info(): project_ids = [] projects = tlc.getProjects() for project in projects: project_ids.append({project['name']: project['id']}) return project_idsdef get_projects_id(): project_ids = [] projects = tlc.getProjects() for project in projects: project_ids.append(project['id']) return project_idsdef get_suites(suite_id): """ 擷取用例集 :return: """ try: suites = tlc.getTestSuiteByID(suite_id) return suites except testlink.testlinkerrors.TLResponseError as e: # traceback.print_exc() logger.warning(str(e).split('\n')[1]) logger.warning(str(e).split('\n')[0]) returndef readExcel(file_path): """ 讀取用例資料 :return: """ case_list = [] try: book = xlrd.open_workbook(file_path) # 開啟excel except Exception as error: logger.error('路徑不在或者excel不正確 : ' + str(error)) return error else: sheet = book.sheet_by_index(0) # 取第一個sheet頁 rows = sheet.nrows # 取這個sheet頁的所有行數 for i in range(rows): if i != 0: case_list.append(sheet.row_values(i)) # 把每一條測試案例添加到case_list中 return case_listdef check_excel_data(func): """ 參數有效性校正 :param func: :return: """ def _check(*args, **kw): global count_fail global count_success # 校正項目ID及測試集ID的有效性 if not args[0] in get_projects_id(): logger.error('project_id is not auth') return if not get_suites(args[1]): logger.error('father_id is not auth') return # 檢測測試資料的有效性 for k, v in kw.items(): if v == "" and k not in ['summary', 'importance']: logger.warning("TestCase '{title}' Parameter '{k}' is null".format(title=kw['title'], k=k)) try: func(args[0], args[1], kw) count_success += 1 except Exception as e: logger.error(e) count_fail += 1 return _checkdef format_info(source_data): """ 轉換Excel中文關鍵字 :param source_data: :return: """ switcher = { "低": 1, "中": 2, "高": 3, "自動化": 2, "手工": 1 } return switcher.get(source_data, "Param not defind")@check_excel_datadef create_testcase(test_project_id, suits_id, data): """ :param test_project_id: :param suits_id: :param data: :return: """ # 設定優先權預設值及摘要預設值 if data['importance'] not in [1, 2, 3]: data['importance'] = 3 if data["summary"] == "": data["summary"] = "無" # 初始化測試步驟及預期結果 for i in range(0, len(data["step"])): tlc.appendStep(data["step"][i][0], data["step"][i][1], data["automation"]) tlc.createTestCase(data["title"], suits_id, test_project_id, data["authorlogin"], data["summary"], preconditions=data["preconditions"], importance=data['importance'], executiontype=2)def excute_creat_testcase(test_project_id, test_father_id, test_file_name): # 對project_id father_id 做有效性判斷 if test_project_id not in get_projects_id(): logger.error('project_id is not auth') return if not get_suites(test_father_id): logger.error('father_id is not auth') return # 擷取用例 test_cases = readExcel(os.path.join('testCase', test_file_name)) if not isinstance(test_cases, collections.Iterable): return # 格式化用例資料 for test_case in test_cases: testCase_data = { "title": test_case[0], "preconditions": test_case[1], "step": list(zip(test_case[2].split('\n'), test_case[3].split('\n'))), # 以分行符號作為測試步驟的分界 "automation": format_info(test_case[4]), # 1 手工, 2 自動 "authorlogin": test_case[5], "importance": format_info(test_case[6]), "summary": test_case[7] } create_testcase(test_project_id, test_father_id, **testCase_data) logger.info("本次操作共提交 {} 條資料,成功匯入 {} 條,失敗 {} 條".format(count_success + count_fail, count_success, count_fail))if __name__ == "__main__": url = "http://localhost/testlink/lib/api/xmlrpc/v1/xmlrpc.php" # 替換為testlink對應URL key = "3aca080de61e3e24b5be209a23fa0652" # 這個key是錯誤的key,登陸testlink後點擊上方個人帳號進入個人中心,新頁面點擊 '產生新的秘鑰'擷取 file_name = "testCase_Example.xlsx" project_id = "2354879" # 可以通過 print(get_projects_info())擷取 father_id = "2054879" # 滑鼠選中想要上傳用例的用例集,點擊右鍵擷取父節點ID tlc = testlink.TestlinkAPIClient(url, key) # print("項目資訊: ", get_projects_info()) excute_creat_testcase(project_id, father_id, file_name)
logger內容
#! /usr/bin/python# coding:utf-8 """ @author:Bingo.he @file: logger_better.py @time: 2018/02/12 """ import loggingimport timeimport oscur_path = os.path.dirname(os.path.realpath(__file__))log_path = os.path.join(cur_path, 'logs')if not os.path.exists(log_path): os.mkdir(log_path)class Log(): def __init__(self, logger, logname='{}.log'.format(time.strftime('%Y-%m-%d'))): self.logname = os.path.join(log_path, logname) self.logger = logging.getLogger(logger) self.logger.setLevel(logging.DEBUG) self.formatter = logging.Formatter('[%(asctime)s]-[%(name)s]-%(levelname)s: %(message)s') def __console(self, level, message): fh = logging.FileHandler(self.logname, 'a', encoding='utf-8') fh.setLevel(logging.DEBUG) fh.setFormatter(self.formatter) self.logger.addHandler(fh) ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) ch.setFormatter(self.formatter) self.logger.addHandler(ch) if level == 'info': self.logger.info(message) elif level == 'debug': self.logger.debug(message) elif level == 'warning': self.logger.warning(message) elif level == 'error': self.logger.error(message) self.logger.removeHandler(ch) self.logger.removeHandler(fh) fh.close() def debug(self, message): self.__console('debug', message) def info(self, message): self.__console('info', message) def warning(self, message): self.__console('warning', message) def error(self, message): self.__console('error', message)if __name__ == "__main__": log = Log(os.path.basename(__file__)) log.info("---測試開始----") log.info("操作步驟1,2,3") log.warning("----測試結束----")
其他:
- 用例步驟分隔字元:當前使用分行符號分隔,可修改excute_creat_testcase函數中testCase_data的step參數
- Excel中作者資訊必須與提供的key值對應
測試案例格式
在此感謝該API的作者。
Python testlink API Github項目地址
【Python】實現將Excel編寫的用例上傳到testlink指定用例集