一、項目框架如圖:
1、common :這個包都是一些公共的方法,如:手機號加解密,get/post接口請求的方法封裝,接口鑒權,發郵件,讀寫excel文件方法等等
2、result:存放每次運行的log和測試報告
3、testcase:這個包放test開頭的測試用例
4、testFile:這個包放接口上傳的圖片(如注冊需要上傳頭像),excel管理的接口參數
5、caselist.txt:需要運行的用例
6、config.ini :放一些配置信息,如發郵件的房間賬戶,接口需要使用的固定參數和版本,發送郵件的開關,以及動態的數據,如動態更改了就將最新的寫在這個配置里面,其他地方需要用的就從配置文件里面取最新生成的。
7、readConfig.py :操作配置文件的一些方法,獲取數據,修改數據等
8、runAll.py:運行所有用例
2、excel表里面的參數:
后面這個code和msg是預期結果,用例里面會獲取實際結果,然后跟這個預期結果比較判斷接口是否成功。
3、接口的寫法
接口是采用參數化實現的,傳入不用的參數對比不同的結果
aes = aesCryter.AesCrypter() authen= authentication.getAuthentication() login_xls = commons.get_xls("userCase.xlsx", "login") localReadConfig = readConfig.ReadConfig() configHttp = ConfigHttp.ConfigHttp() info = {} @paramunittest.parametrized(*login_xls) class Login(unittest.TestCase): def setParameters(self, case_name,url, method, token, par, code, msg): self.case_name = str(case_name) self.url = str(url) self.method = str(method) self.token = str(token) self.par = eval(str(par)) self.code = str(code) self.msg = str(msg) self.return_json = None self.info = None def setUp(self): self.log = Log.MyLog.get_log() self.logger = self.log.get_logger() print(self.case_name+"測試開始前准備") def testLogin(self): get_url = authen.get_Url("userCase.xlsx", "login",0,1) ydtoken = authen.get_ydtoken(url = get_url) #獲取ydtoken new_url =localReadConfig.get_http('url')+get_url+"&ydtoken="+ydtoken #拼接接口的請求鏈接 configHttp.set_url(new_url) print("第一步:設置url "+new_url) # get visitor token if self.token == '0': token_v = None elif self.token == '1': businessCommon.set_visitor_token_to_config() token_v = localReadConfig.get_headers('token_v') header = {"cookie": "SSO=%s" % str(token_v)} configHttp.set_headers(header) print("第二步:設置header(token等)") # set params data =self.par data['mobile'] = aes.encrypt(str(data['mobile'])) #對手機號和密碼繼續加密 data['password'] = aes.encrypt(str(data['password'])) data["token"] = str(token_v) configHttp.set_data(data) print("第三步:設置發送請求的參數") # test interface self.return_json = configHttp.post() print(self.return_json) print("第四步:發送請求方法") # check result self.checkResult() print("第五步:檢查結果") def tearDown(self): """ :return: """ self.log.build_case_line(self.case_name, actualcode, actualmsg) print("測試結束,輸出log完結\n\n") def checkResult(self): """ check test result :return: """ global actualcode,actualmsg actualcode = commons.get_value_from_return_json(self.return_json, 'code') print('實際code:%s'%actualcode) actualmsg = commons.get_value_from_return_json(self.return_json, 'msg') print('實際msg:%s'%actualmsg) self.assertEqual(actualcode, self.code) self.assertEqual(actualmsg, self.msg) if __name__ == '__main__': unittest.main
4、接口關聯,
接口和接口之間有這依賴關系,必須上一個接口請求完成,后面這個接口才能才能,所以在common公共包里面寫了一個通用的方法,如果涉及到有依賴關系的,就調用這個接口,把需要先請求的接口先完成了,再請求要測試的接口
比如:接下來這個忘記密碼接口,更改密碼,必須先請求發送驗證碼接口,再請求驗證已驗證接口,最后才能請求更改密碼接口
import unittest import paramunittest import readConfig as readConfig from common import Log as Log from common import commons from common import configHttp as ConfigHttp from common import businessCommon from common import get_Authentication as authentication authen= authentication.getAuthentication() forgotcheck = commons.get_xls("userCase.xlsx", "forgotcheck") localReadConfig = readConfig.ReadConfig() configHttp = ConfigHttp.ConfigHttp() info = {} @paramunittest.parametrized(*forgotcheck) class ForgotCheck(unittest.TestCase): def setParameters(self, case_name, url,method, token, par, code, msg): self.case_name = str(case_name) self.url = str(url) self.method = str(method) self.token = str(token) self.par = eval(str(par)) self.code = str(code) self.msg = str(msg) self.return_json = None self.info = None def setUp(self): self.log = Log.MyLog.get_log() self.logger = self.log.get_logger() print(self.case_name+"測試開始前准備") def testforgotcheck(self): # set url get_url = authen.get_Url("userCase.xlsx", "forgotcheck", 0, 1) ydtoken = authen.get_ydtoken(url=get_url) # 獲取ydtoken new_url = localReadConfig.get_http('url') + get_url + "&ydtoken=" + ydtoken # 拼接鑒權的請求鏈接 configHttp.set_url(new_url) print("第一步:設置url " + new_url) # get visitor token if self.token == '0': token_v = None elif self.token == '1': businessCommon.set_visitor_token_to_config() token_v = localReadConfig.get_headers('token_v') header = {"cookie": "SSO=%s" % str(token_v)} configHttp.set_headers(header) print("第二步:設置header(token等)") # set params data = self.par data["token"] = str(token_v) configHttp.set_data(data) print("第三步:設置發送請求的參數") # test interface self.return_json = configHttp.post() print("第四步:發送請求方法") # check result self.checkResult() print("第五步:檢查結果") def tearDown(self): """ :return: """ self.log.build_case_line(self.case_name, actualcode, actualmsg) print("測試結束,輸出log完結\n\n") def checkResult(self): """ check test result :return: """ global actualcode,actualmsg actualcode = commons.get_value_from_return_json(self.return_json, 'code') print('實際code:%s'%actualcode) actualmsg = commons.get_value_from_return_json(self.return_json, 'msg') print('實際msg:%s'%actualmsg) self.assertEqual(actualcode, self.code) self.assertEqual(actualmsg.strip(), self.msg)
5、控制接口是否需要運行 ,每次新增用例把用例名字寫在這個 caselist.txt ,不需要運行就注釋即可。
#reqSer/test_001_getRequst #reqSer/test_002_addRequst #reqSer/test_003_userRadar user/test_001_Login #user/test_002_Sign_sms #user/test_003_Forgotsms #user/test_004_Forgotcheck #user/test_005_forgotpass #user/test_006_NoParameterization
6、運行所有用例 runAll.py
import os import unittest from common.Log import MyLog as Log import readConfig as readConfig from common import HTMLTestRunner from common.configEmail import MyEmail localReadConfig = readConfig.ReadConfig() class AllTest: def __init__(self): global log, logger, resultPath, on_off log = Log.get_log() logger = log.get_logger() resultPath = log.get_report_path() print(resultPath) on_off = localReadConfig.get_email("on_off") self.caseListFile = os.path.join(readConfig.proDir, "caselist.txt") self.caseFile = os.path.join(readConfig.proDir, "testCase") # self.caseFile = None self.caseList = [] self.email = MyEmail.get_email() def set_case_list(self): """ set case list :return: """ fb = open(self.caseListFile) for value in fb.readlines(): data = str(value) if data != '' and not data.startswith("#"): self.caseList.append(data.replace("\n", "")) fb.close() def set_case_suite(self): """ set case suite :return: """ self.set_case_list() test_suite = unittest.TestSuite() suite_module = [] for case in self.caseList: case_name = case.split("/")[-1] print(case_name+".py") discover = unittest.defaultTestLoader.discover(self.caseFile, pattern=case_name + '.py', top_level_dir=None) suite_module.append(discover) if len(suite_module) > 0: for suite in suite_module: for test_name in suite: test_suite.addTest(test_name) else: return None return test_suite def run(self): """ run test :return: """ try: suit = self.set_case_suite() if suit is not None: logger.info("********TEST START********") fps = open(resultPath, 'wb') runner = HTMLTestRunner.HTMLTestRunner(stream=fps, title='Test Report', description='Test Description') runner.run(suit) else: logger.info("Have no case to test.") except Exception as ex: logger.error(str(ex)) logger.info("*********TEST END*********") fps.close() # send test report by email if on_off == 'on': self.email.send_email() elif on_off == 'off': logger.info("Doesn't send report email to developer.") else: logger.info("Unknow state.") if __name__ == '__main__': obj = AllTest() obj.run()
6、生成的報告:
7、發送郵件,郵件附件是report和log,所以壓縮了一下。