def importTestCase(self, testCaseList): ''' 动态添加测试用例的引用 :param testCaseList: :return: ''' classList = [] testCaseDir = settings.TESTCASE['testCaseDir'] for dict in testCaseList: try: p = dict['testCase'] p = p[1:] if p[:1] == '/' else p if not p.startswith(testCaseDir): p = testCaseDir + p path = p path = path.replace('/', '.') path = path[1:] if path[:1] == '.' else path model_module = importlib.import_module(path) # 引入模块 except Exception as e: err = '[ERROR-1004]:引入测试方案模块失败引发的异常.%s.%s' % (dict['testCase'], e) putSystemLog(err, self.logger, True, RunStatus.RUNNING, RunResult.ERROR, True, '异常') continue for attr_name in dir(model_module): attr = getattr(model_module, attr_name) try: if issubclass(attr, TestCase) and attr.__name__ != TestCase.__name__: classList.append( {'paramPath': dict['paramPath'], 'testClass': attr, 'className': attr.__name__, 'scriptPath': '%s' % (p), 'scriptId': dict['scriptId']}) except Exception: continue return classList
def importTestCase(self, testCaseList): ''' 动态添加测试用例的引用 :param testCaseList: :return: ''' classList = [] for dict in testCaseList: try: p = dict['testCase'] path = self.getModule(p) model_module = importlib.import_module(path) # 引入模块 except Exception as e: err = '[ERROR-1004]:引入测试方案模块失败引发的异常.%s.%s' % (dict['testCase'], e) putSystemLog(err, self.logger, True, RunStatus.RUNNING, RunResult.ERROR, True, '异常') continue for attr_name in dir(model_module): attr = getattr(model_module, attr_name) try: if issubclass( attr, TestCase) and attr.__name__ != TestCase.__name__: classList.append({ 'paramPath': dict['paramPath'], 'testClass': attr, 'className': attr.__name__, 'scriptPath': '%s' % (p), 'scriptId': dict['scriptId'] }) except Exception: continue self.testClassList = classList
def loadTestPlanXML(self): ''' 加载测试用例配置文件 :return: ''' try: if not isAbsolutePath(self.xmlPath): self.xmlPath = pathJoin(settings.TESTCASE['xmlDir'], self.xmlPath) tree = ET.parse(self.xmlPath) # 打开xml文档 root = tree.getroot() # 获得root节点 for child in root: if child.tag == settings.XML_TAG['testPlan']['connection']: if len(self.hubDict) == 0: self.hubDict = self.getHubDict(child) elif child.tag == settings.XML_TAG['testPlan']['scene']: sceneId = child.get( settings.XML_TAG['testPlan']['sceneid']) # sceneId settings.SCENEID = sceneId testCaseList = self.getTestList(child) # 读取一个场景中的所有测试用例 testScene = TestScene(sceneId, testCaseList) self.testPlan.append(testScene) # 将测试用例列表添加到测试方案中 except Exception as e: putSystemLog('[ERROR-1001]:读取测试方案配置文件引发的异常.%s' % (e), None, True, RunStatus.END, RunResult.ERROR, True, '异常') raise
def getUploadFiles(self, value): # 上传 scriptId = self._driver.logger.scriptId tempFilesList = [] filesDir = pathJoin(settings.TESTCASE['filesDir'], scriptId) # 上传文件夹 for x in range(len(value)): try: filePath = pathJoin(filesDir, os.path.basename(value[x])) if os.path.isfile(filePath): tempFilesList.append(filePath) continue filePath = value[x].replace('\\', '/') if not isAbsolutePath(filePath): filePath = pathJoin(settings.TESTCASE['filesDir'], filePath) if os.path.isfile(filePath): tempFilesList.append(filePath) else: raise UploadFilePathException('', filePath) except Exception as e: putSystemLog(e, self._driver.logger, True, RunStatus.RUNNING, RunResult.ERROR, True, '异常') return tempFilesList
def updateSettings(self, model): if model == RunModel.TESTING: # 测试模式 settings.RUNMODEL = model settings.TESTCASE['runType'] = RunType.BROWSER if model == RunModel.ONLINE: # 在线模式 settings.RUNMODEL = model try: decodeJson = json.loads(self.uniqueCode.replace("'", "\"")) hubDict = {} for browser in decodeJson['browsers'].keys(): br = browser.lower()[:2] if br in BROWSER_ID: hubDict[br] = decodeJson['browsers'][browser] break self.hubDict = hubDict settings.SERVER['requestURL'] = decodeJson['requestURL'] except Exception as e: putSystemLog('[ERROR-1002]:解析外部传入的JSON字符串引发的异常.%s' % e, None, False, '', '', True) raise settings.TESTCASE['runType'] = RunType.REMOTE settings.REPORT['isWriteLog'] = True if model == RunModel.NORMAL: # 正常模式 settings.RUNMODEL = model # 修正 if isNoneOrEmpty(settings.SERVER['requestURL']): # 如果服务器url不正确,就不发送数据 settings.SERVER['isRequest'] = False
def start(self): try: if self.testType == TestType.UI: uiTest.Main(self.xmlPath).run() elif self.testType == TestType.INTERFACE: interfaceTest.Main(self.xmlPath).run() except Exception as e: putSystemLog('[ERROR-0002-0]:选择测试方式时发生异常.%s' % e, None, False, '', '', True)
def getDriverObj(self): try: driver = self._driverFunc() # 创建浏览器驱动 driver.logger = self.logger # 为浏览器驱动配置日志对象 driver.screenShotDir = self.screenShotDir # 为浏览器驱动配置截图目录 driver.sceneId = self.sceneId # 为浏览器驱动配置场景ID return driver except Exception as e: putSystemLog('[ERROR-1008]:创建浏览器驱动对象失败引发的异常.%s' % e, self.logger, True, RunStatus.RUNNING, RunResult.ERROR, True, '异常') raise
def start(self): # 配置场景 try: runType = settings.TESTCASE['runType'] if astrcmp(runType, RunType.REMOTE): self.__onLine() elif astrcmp(runType, RunType.BROWSER): self.__offLine() except Exception as e: putSystemLog('[ERROR-1003]:配置场景引发的异常.%s' % (e), None, True, RunStatus.END, RunResult.ERROR, True, '异常') raise
def createDir(dir, addDateDir=True): dirPath = dir if addDateDir: date = time.strftime('%Y%m%d', time.localtime()) dirPath = os.path.join(dir, date) time.sleep(random.uniform(0, 1)) # 延迟等待0-1秒 try: if not os.path.exists(dirPath): os.makedirs(dirPath) except Exception as e: putSystemLog('[ERROR-0004-0]:创建日志目录失败引发的异常.%s' % e, None, False, '', '', True) return dirPath
def updateOnlineModel(self): ''' 该方法内更新在线模式的全局设置 :return: ''' settings.RUNMODEL = self.model settings.REPORT['isWriteLog'] = False try: settings.SERVER['requestURL'] = self.json['requestURL'] except Exception as e: putSystemLog('[ERROR-0001-2]:解析json字符串中requestURL发生异常.%s' % e, None, False, '', '', True) raise
def run(self): if isNoneOrEmpty(self.xmlPath): # 当没有传入测试方案的时候,从控制台获取 self.setTestPlanPathFromUser() testPlanName = self.xmlPath #测试方案文件名称 putSystemLog('程序启动.%s' % testPlanName, None, False, '', '', True) try: self.setRunModel() # 设置运行模式 self.updateSettings(self.model) # 根据运行模式更新settings设置 self.loadTestPlanXML() # 加载测试方案配置文件 self.start() # 启动 except Exception as e: pass finally: putSystemLog('程序结束.%s\n' % testPlanName, None, False, '', '', True)
def updateOnlineModel(self): super(Main, self).updateOnlineModel() try: hubDict = {} for browser in self.json['browsers'].keys(): br = browser.lower()[:2] if br in BROWSER_ID: hubDict[br] = self.json['browsers'][browser] break self.testPlan.hubDict = hubDict # 在线模式下,hub由外部参数传入 except Exception as e: putSystemLog('[ERROR-1015]:解析json字符串时引发的异常.%s' % e, None, False, '', '', True) raise settings.TESTCASE['runType'] = RunType.REMOTE
def loadXml(self): try: tree = xmlHelper.read_xml(self.xmlPath) if self.testType == TestType.UI: #UI测试需要获取hub信息 connection_nodes = xmlHelper.find_nodes( tree, settings.XML_TAG['testPlan']['connection']) if len(connection_nodes) > 0: self.setHubDict(connection_nodes[0]) scene_nodes = xmlHelper.find_nodes( tree, settings.XML_TAG['testPlan']['scene']) if len(scene_nodes) > 0: self.setSceneList(scene_nodes) except Exception as e: putSystemLog('[ERROR-0003-0]:解析测试方案配置文件引发的异常.%s' % (e), None, True, RunStatus.END, RunResult.ERROR, True, '异常') raise
def runTestPlan(self): ''' 运行测试方案 :return: ''' logger= self.createLoggerObj() #创建日志 result = RunResult.PASS err = '' putSystemLog('Start.', logger, True, RunStatus.START, result, True, '开始') try: for index, scene in enumerate(self.testPlan.sceneList): Scene(scene, logger, index).run() except Exception as e: result = RunResult.ERROR err = e finally: putSystemLog('End.%s' % (err), logger, True, RunStatus.END, result, True, '结束')
def setTestType(self): settings.JSON_UNIQUECODE = None #外部传入的json唯一码 if self.uniqueCode: try: settings.JSON_UNIQUECODE = json.loads( self.uniqueCode.replace("'", "\"")) except Exception as e: putSystemLog('[ERROR-0001-0]:解析json字符串引发的异常.%s' % e, None, False, '', '', True) raise if settings.JSON_UNIQUECODE: try: self.testType = settings.JSON_UNIQUECODE[ 'testType'] # 还没提供字段 except Exception as e: putSystemLog( '[ERROR-0001-1]:解析json字符串中testType发生异常.%s' % e, None, False, '', '', True) raise
def setUp(self): putSystemLog('开始运行脚本%s' % (str(self.__class__)), self.logger) try: self.initProjectObj() # 根据不同项目动态初始化对象 self.initRequestData() # 初始化请求参数数据 except JsonLoadsException as e: putSystemLog(e, self.logger, True, RunStatus.RUNNING, RunResult.ERROR, True, '异常') except Exception as e: putSystemLog('[ERROR-2007-0]:测试用例初始化数据引发的异常.请检查参数是否配置正确%s' % e, self.logger, True, RunStatus.RUNNING, RunResult.ERROR, True, '异常') raise
def run(self): super(Main, self).run() testPlanName = self.xmlPath # 测试方案文件名称 putSystemLog('Interface程序启动.测试方案名称:%s' % testPlanName, None, False, '', '', True) try: self.setAbsoluteXmlPath() self.testPlan = TestPlan(self.xmlPath, self.testType) # 创建测试方案对象 self.setRunModel() # 设置运行模式 self.updateSettings() # 根据运行模式更新settings设置 self.testPlan.loadXml() # 从xml文件中读取测试方案 self.start() # 启动 except Exception as e: putSystemLog('[ERROR-2001-0]:接口测试中未能有效捕获的异常.%s' % e, None, False, '', '', True) finally: putSystemLog('Interface程序启动程序结束.测试方案名称:%s\n' % testPlanName, None, False, '', '', True)
def compareResult(self): param = self.param r = self.response expectType = param.expectType putSystemLog('响应值:%s' % (r.status_code), self.logger, True, RunStatus.RUNNING, RunResult.PASS, True, '响应值') if expectType == RequestDataType.JSON: if isNoneOrEmpty(self.param.expect): pass else: compareResult = self.compare() putSystemLog('Json对比结果:%s,%s' % compareResult[0], compareResult[1], self.logger, True, RunStatus.RUNNING, RunResult.PASS, True, 'Json对比结果') elif expectType == RequestDataType.STRING: putSystemLog(r.text, self.logger)
def __runTestPlan(self, driver): logger = self.createLoggerObj() # 创建该场景日志对象 screenShotDir = self.createScreenShotDir() # 创建截图目录 result = RunResult.PASS err = '' putSystemLog('Start.', logger, True, RunStatus.START, result, True, '开始') try: for index, sc in enumerate(self.testPlan): Scene(driver, sc, logger, screenShotDir, index).run() except Exception as e: result = RunResult.ERROR err = e finally: putSystemLog('End.%s' % (err), logger, True, RunStatus.END, result, True, '结束') putSystemLog( getRecordTxt(manageLogRecord(operator='get'), type='all'), logger) # 写入统计结果
def suiteFactory(self): suite = TestSuite() # 创建测试单元套件 for index, testCaseClass in enumerate(self.testClassList): try: paramPath = testCaseClass['paramPath'] # 获取参数文件地址 if paramPath and os.path.exists(paramPath): paramsList = self.readParamXml(paramPath, testCaseClass['className']) else: continue # 接口测试必须传入参数文件 for i, params in enumerate(paramsList): if len(params) == 0: continue scriptId = testCaseClass['scriptId'] if testCaseClass[ 'scriptId'] else '' # 添加临时脚本id jsonParam = { 'scriptId': scriptId, 'paramsDict': params, 'logger': self.logger, 'sceneId': self.sceneId } # 传递给测试用例的参数 suite.addTest(testCaseClass['testClass']( jsonParam)) # 创建测试用例,并添加到套件中 putSystemLog('脚本<%d_%d>:加载成功.' % (index + 1, i + 1), self.logger) # putSystemLog('脚本<%d_%d>参数列表:' % (index + 1, i + 1), self.logger) # for k, v in params.items(): # putSystemLog("%s:%s" % (k, v), self.logger) except ReadParamFileException as e: putSystemLog(e, self.logger, True, RunStatus.RUNNING, RunResult.ERROR, True) except Exception as e: err = '[ERROR-2005-0]:向测试单元套件添加测试用例对象时引发的异常.%s.%s' % ( testCaseClass['scriptPath'], e) putSystemLog(err, self.logger, True, RunStatus.RUNNING, RunResult.ERROR, True) return suite
def suiteFactory(self, x, driver): suite = unittest.TestSuite() # 创建测试单元套件 number = 1 for testCaseClass in self.__testClassList: paramPath = testCaseClass['paramPath'] # 获取参数文件地址 if paramPath != None and paramPath.strip() != '': paramsList = self.readParamXml(paramPath, testCaseClass['className'], x) else: paramsList = None suite.addTest(testCaseClass['testClass']( driver, paramsList)) #创建测试用例,并添加到套件中 scriptName = testCaseClass['scriptPath'].split('/')[-1] putSystemLog( '脚本<%d>:%s 加载成功.脚本路径:%s' % (number, scriptName, testCaseClass['scriptPath']), self.logger) if paramsList != None: putSystemLog('脚本<%d>参数列表:' % (number), self.logger) for k, v in paramsList.items(): putSystemLog("%s:%s" % (k, v), self.logger) number = number + 1 return suite
def setUp(self): putSystemLog('=' * 40, self.logger) putSystemLog('开始运行脚本%s' % (str(self.__class__)), self.logger)
def putInfoToLog(self): putSystemLog('-' * 40, self.logger) putSystemLog('测试项目名称:%s(%s)' % (self.projectObj.name, self.param.projectClass), self.logger) putSystemLog('待测试接口:%s' % self.param.url, self.logger) putSystemLog('请求方式:%s' % self.param.method, self.logger) putSystemLog('请求数据类型:%s' % (self.param.dataType), self.logger) putSystemLog('返回数据类型:%s' % (self.param.expectType), self.logger) putSystemLog('结果对比:%s' % ','.join([INTERFACE_PARAMS['resultCompare'][x] for x in self.param.resultCompare]), self.logger) putSystemLog('请求参数:%s' % (json.dumps(self.requestData, indent=4)), self.logger) putSystemLog('-' * 40, self.logger)
def importTestCase(self, testCaseList): ''' 动态添加测试用例的引用 由于参数化文件中包含接口测试的必选项 所以每一条测试用例,必须包含参数化文件,但脚本不是必须的 如果不包含脚本,会加载默认的测试用例脚本 :param testCaseList: :return: ''' classList = [] for index, dict in enumerate(testCaseList): paramPath = dict['paramPath'] if not paramPath: err = '[ERROR-2002-0]:场景<%d>-用例<%d>,未发现参数化文件,该用例被忽略.' % ( self.sceneId, index) putSystemLog(err, self.logger, True, RunStatus.RUNNING, RunResult.ERROR, True) continue model_module = None try: p = dict['testCase'] if p: path = self.getModule(p) model_module = importlib.import_module(path) # 引入模块 except Exception as e: err = '[ERROR-2003-0]:引入测试方案模块失败引发的异常.%s.%s' % ( dict['testCase'], e) putSystemLog(err, self.logger, True, RunStatus.RUNNING, RunResult.ERROR, True) continue if model_module: ''' 配置文件中有脚本的时候,根据脚本创建测试用例对象 ''' for attr_name in dir(model_module): attr = getattr(model_module, attr_name) try: if issubclass(attr, TestCase ) and attr.__name__ != TestCase.__name__: classList.append({ 'paramPath': dict['paramPath'], 'testClass': attr, 'className': attr.__name__, 'scriptPath': '%s' % (p), 'scriptId': dict['scriptId'] }) except Exception: continue else: ''' 配置文件中没有脚本的是,创建默认测试用例对象 ''' classList.append({ 'paramPath': dict['paramPath'], 'testClass': EasyCase, 'className': EasyCase.__name__, 'scriptPath': None, 'scriptId': dict['scriptId'] }) self.testClassList = classList
def tearDown(self): putSystemLog('脚本运行完毕...', self.logger) putSystemLog('=' * 40+'\n', self.logger)
def run(self): logger = self.logger # 日志对象 runTime = settings.PARAMETERIZATION['runTime'] # 单个场景运行次数 runModel = settings.RUNMODEL # 运行模式 manageLogRecord(self.sceneId, operator='create') # 创建统计记录 self.testClassList = self.importTestCase(self.testCaseList) # 引入测试用例 if len(self.testClassList) == 0: putSystemLog('[ERROR-1009]:场景%d中不包含任何测试用例' % self.sceneId, logger, False, RunStatus.RUNNING, RunResult.ERROR, True) return if runModel == RunModel.TESTING: putSystemLog('启动测试模式下,不会真正运行测试用例的脚本!', logger) sceneDes = '场景<%d>开始.' % (self.sceneId) if runTime == 1 else '场景<%d>开始.该场景共运行%d次' % (self.sceneId, runTime) putSystemLog(sceneDes, logger) sTime = time() driver =None for x in range(runTime): try: if runTime != 1: putSystemLog('第%d次运行:' % (x + 1), logger) driver = self.getDriverObj() # 获取一个浏览器驱动 putSystemLog('%s浏览器启动成功.' % (driver.name), logger) putSystemLog('开始加载脚本...', logger) suite = self.suiteFactory(x, driver) # 创建并配置测试单元套件 putSystemLog('脚本加载完成...', logger) if runModel != RunModel.TESTING and len(suite._tests) > 0: TextTestRunner().run(suite) except createDriverException as e: putSystemLog(str(e), logger, True, RunStatus.RUNNING, RunResult.ERROR, True, '异常') except Exception as e: putSystemLog('[ERROR-1012]:测试套件运行失败引发的异常.%s' % e, logger, True, RunStatus.RUNNING, RunResult.ERROR, True, '异常') finally: self.quitDriver(driver) eTime = time() putSystemLog('场景<%d>结束.用时:%.3fs.' % (self.sceneId, eTime - sTime), logger) putSystemLog(getRecordTxt(manageLogRecord(self.sceneId, operator='get')), logger) putSystemLog('-' * 40, logger)
def setUp(self): putSystemLog('开始运行脚本%s' % (str(self.__class__)), self._driver.logger) if EasyConfig().maxWindow: self._driver.maximize_window()
def suiteFactory(self, x, driver): suite = TestSuite() # 创建测试单元套件 for index, testCaseClass in enumerate(self.testClassList): try: paramsList = None # 参数列表 paramPath = testCaseClass['paramPath'] # 获取参数文件地址 if paramPath and os.path.exists(paramPath): paramsList = self.readParamXml(paramPath, testCaseClass['className'], x) except ReadParamFileException as e: putSystemLog(e, self.logger, True, RunStatus.RUNNING, e.runResult, True, '参数文件异常') except Exception as e: err = '读取参数化文件时发生异常.%s.%s' % (testCaseClass['scriptPath'], e) putSystemLog(err, self.logger, True, RunStatus.RUNNING, RunResult.ERROR, True, '异常') try: driver.scriptId = testCaseClass['scriptId'] if testCaseClass['scriptId'] else '' # 添加临时脚本id suite.addTest(testCaseClass['testClass'](driver, paramsList)) # 创建测试用例,并添加到套件中 scriptName = testCaseClass['scriptPath'].split('/')[-1] putSystemLog('脚本<%d>:%s 加载成功.脚本路径:%s' % (index + 1, scriptName, testCaseClass['scriptPath']), self.logger) if paramsList is not None: putSystemLog('脚本<%d>参数列表:' % (index + 1), self.logger) for k, v in paramsList.items(): putSystemLog("%s:%s" % (k, v), self.logger) except Exception as e: err = '[ERROR-1011]:向测试单元套件添加测试用例对象时引发的异常.%s.%s' % (testCaseClass['scriptPath'], e) putSystemLog(err, self.logger, True, RunStatus.RUNNING, RunResult.ERROR, True, '异常') return suite
def tearDown(self): putSystemLog('脚本运行完毕...', self._driver.logger)
def run(self): logger = self.logger for x in range(int(EasyConfig().runTime)): try: putSystemLog('程序开始.', logger) putSystemLog('正在初始化....', logger) sTime = time() driver = self.getDriverObj() # 获取一个浏览器驱动 putSystemLog('%s浏览器启动成功.' % (driver.name), logger) putSystemLog('开始加载脚本...', logger) suite = self.suiteFactory(x, driver) # 创建并配置测试单元套件 putSystemLog('脚本加载完成...', logger) unittest.TextTestRunner().run(suite) except Exception as e: putSystemLog('程序运行过程中发生异常.', logger) putSystemLog(e, logger) raise finally: driver.quit() eTime = time() putSystemLog('程序结束,用时:%.3fs.' % (eTime - sTime), logger)