一.思想:html
基於數據驅動和代碼驅動結合的自動化測試框架。python
二.自動化測試框架步驟:json
1.獲取用例,用例格式:.ymalapi
2.調用接口cookie
3.校驗結果框架
4.發送測試報告函數
5.異常處理佈局
6.日誌模塊post
三.基於上一篇文章中,使用unittest模塊框架,編寫自動化調用接口測試,拷貝生成用例的python文件做爲模板,在conf下新建base.txt,只需每次修改文件中類名:和文件名:生成一樣的python文件做爲用例便可。學習
base.txt以下:
import unittest,requests import ddt from BeautifulReport import BeautifulReport as bf from BeautifulReport import BeautifulReport as bf from urllib import parse from conf.setting import BASE_URL @ddt.ddt class %s(unittest.TestCase): #是百分號s指變量class_name base_url = BASE_URL @ddt.file_data(r'%s')#ddt幫你讀文件,獲取文件內容,循環調用函數 百分號s是指變量file_name def test_request(self,**kwargs): detail = kwargs.get('detail','沒寫用例描述') self._testMethodDoc = detail #動態的用例描述 url = kwargs.get('url')#url url = parse.urljoin(self.base_url,url)#拼接好url method = kwargs.get('method','get')#請求方式 data = kwargs.get('data',{}) #請求參數 header = kwargs.get('header',{})#請求頭 cookie = kwargs.get('cookie',{})#cookie check = kwargs.get('check') method = method.lower() #便於處理 try: if method=='get': res = requests.get(url,params=data,cookies=cookie,headers=header).text #由於接口有異常的狀況下, 可能返回的不是json串,會報錯 else: res = requests.post(url,data=data,cookies=cookie,headers=header).text except Exception as e: print('接口請求出錯') res = e for c in check: self.assertIn(c,res,msg='預計結果不符,預期結果:'+c + '實際結果:' +res)
四.自動化框架的文件佈局:
五.寫代碼:
1.新建用例,舉例:註冊reg.yaml和註冊login.yaml
reg.yaml:
2.配置setting文件,將全部文件中用到的變量定義在該文件,須要修改的時候,直接在該文件中修改便可。setting:
import os BASE_PATH = os.path.dirname( #找到utp的目錄 os.path.dirname(os.path.abspath(__file__)) ) MAIL_HOST='smtp.163.com' MAIL_USER='lix.xxxx@163.com' MAIL_PASSWRD = 'xxxxxxxxx1' TO = [ '5472xxxxx@qq.com', ] LEVEL = 'debug' #日誌級別 LOG_PATH = os.path.join(BASE_PATH,'logs') #存放日誌的路徑 CASE_PATH = os.path.join(BASE_PATH,'cases') #存放用例的路徑 YAML_PATH = os.path.join(BASE_PATH,'case_data') #存放yaml文件的路徑 CASE_TEMPLATE = os.path.join(BASE_PATH,'conf','base.txt') #用例模板的路徑 REPORT_PATH = os.path.join(BASE_PATH,'report') #存放報告的目錄 BASE_URL = 'http://118.xx.xx.xx' #接口的地址 LOG_NAME='utp.log' #日誌的文件名
3.在lib文件下新建tools.py:首先判斷case_data下的.yaml文件個數,建立對應的python文件。具體:打開並讀取base.txt文件,將文件中的類和文件名替換後,再建立python文件。生成用例-->運行全部用例:
import datetime import yagmail from lib.log import utp_log #要用到日誌文件 from conf import setting #要用到配置文件中的變量 import os import unittest from BeautifulReport import BeautifulReport as bf #生成報告 def makeCase(): #生成用例 all_yaml = os.listdir(setting.YAML_PATH) #獲取全部的ymal文件 base_case_str = open(setting.CASE_TEMPLATE,encoding='utf-8').read()#讀取到base.txt文件裏的內容,寫在循環外面 for yaml in all_yaml: #判斷讀取的文件是否爲.yaml或.yml if yaml.endswith('.yaml') or yaml.endswith('.yml'):#判斷是不是yml文件 class_name = yaml.replace('.yml','').replace('.yaml','').capitalize()#將文件名的後綴去掉獲取類名,並首字母大寫 file_name = os.path.join(setting.YAML_PATH,yaml)#拼接生成的ymal文件的絕對路徑 content = base_case_str %(class_name,file_name) py_file_name = os.path.join(setting.CASE_PATH,class_name)#拼好生成python文件的絕對路徑 open('%s.py'%py_file_name,'w',encoding='utf-8').write(content) #以w格式打開,保證每次打開ymal文件都會清空從新寫 def run_all_case(): #找到全部的python用例文件,並運行 suite = unittest.TestSuite() #調用unittest模塊的TestSuite(),實例化 all_py = unittest.defaultTestLoader.discover(setting.CASE_PATH,'*.py') #在指定目錄下找python文件:以.py結尾的python文件 #找到全部的python文件 [ suite.addTests(py) for py in all_py] #這裏用addTests,是由於py文件裏可能有多個函數,都要添加進來 #列表生成式,添加文件裏面的case到測試集合裏面 # for py in all_py: #等同於上面的列表生成式 # suite.addTests(py) run=bf(suite) today = datetime.datetime.today().strftime('%Y%m%d%H%M%S') #.strftime將時間格式化取到秒 title = '%s_接口測報告.html'%today report_abs_path = os.path.join(setting.REPORT_PATH,title) #拼接報告的絕對路徑 run.report(title,filename=title,log_path=setting.REPORT_PATH) return run.success_count,run.failure_count,report_abs_path def sendmail(title,content,attrs=None): try: m = yagmail.SMTP(host=setting.MAIL_HOST,user=setting.MAIL_USER ,password=setting.MAIL_PASSWRD ) m.send(to=setting.TO,subject=title, contents=content, attachments=attrs) except Exception as e: msg = '郵件發送失敗,%s'%e utp_log.error(msg)
4.在bin文件下新建run.py,按照邏輯運行文件。分別調用生成用例,運行用例,發報告的類。
import os,sys import datetime BASE_PATH = os.path.dirname( #由於run.py是入口文件,尚未加載setting文件,因此不能找到環境變量,需在此定義BASE_PATH找到utp目錄 os.path.dirname(os.path.abspath(__file__)) ) sys.path.insert(0,BASE_PATH) from lib import tools def main(): tools.makeCase()#自動產生用例的python文件 pass_count,fail_count,abs_path = tools.run_all_case()#運行全部用例並獲取其返回值 msg=''' 各位好! 本次接口測試結果以下: 經過用例:%s條 失敗用例:%s條 詳細信息見附件【%s】。 '''%(pass_count,fail_count,os.path.basename(abs_path)) #os.path.basename()獲取絕對路徑的文件名 today = datetime.datetime.today().strftime('%Y%m%d%H%M%S') title = '接口測試報告_%s'%today #郵件標題 tools.sendmail(title,msg,abs_path) #發送郵件,標題,提示信息,附件 main()
5.生成的python文件舉例,Login.py:
import unittest,requests import ddt from BeautifulReport import BeautifulReport as bf from BeautifulReport import BeautifulReport as bf from urllib import parse from conf.setting import BASE_URL @ddt.ddt class Login(unittest.TestCase): #是百分號s指變量class_name base_url = BASE_URL @ddt.file_data(r'C:\Users\Fancy\Desktop\學習筆記\day11\utp\case_data\login.yaml')#ddt幫你讀文件,獲取文件內容,循環調用函數 百分號s是指變量file_name def test_request(self,**kwargs): detail = kwargs.get('detail','沒寫用例描述') self._testMethodDoc = detail #動態的用例描述 url = kwargs.get('url')#url url = parse.urljoin(self.base_url,url)#拼接好url method = kwargs.get('method','get')#請求方式 data = kwargs.get('data',{}) #請求參數 header = kwargs.get('header',{})#請求頭 cookie = kwargs.get('cookie',{})#cookie check = kwargs.get('check') method = method.lower() #便於處理 try: if method=='get': res = requests.get(url,params=data,cookies=cookie,headers=header).text #由於接口有異常的狀況下, 可能返回的不是json串,會報錯 else: res = requests.post(url,data=data,cookies=cookie,headers=header).text except Exception as e: print('接口請求出錯') res = e for c in check: self.assertIn(c,res,msg='預計結果不符,預期結果:'+c + '實際結果:' +res)
6.log.py,生生日誌的文件:
import logging,os from logging import handlers from conf import setting class MyLogger(): def __init__(self,file_name,level='info',backCount=5,when='D'): logger = logging.getLogger() # 先實例化一個logger對象,先建立一個辦公室 logger.setLevel(self.get_level(level)) # 設置日誌的級別的人 cl = logging.StreamHandler() # 負責往控制檯輸出的人 bl = handlers.TimedRotatingFileHandler(filename=file_name, when=when, interval=1, backupCount=backCount, encoding='utf-8') fmt = logging.Formatter('%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s') cl.setFormatter(fmt) # 設置控制檯輸出的日誌格式 bl.setFormatter(fmt) # 設置文件裏面寫入的日誌格式 logger.addHandler(cl) logger.addHandler(bl) self.logger = logger def get_level(self,str): level = { 'debug':logging.DEBUG, 'info':logging.INFO, 'warn':logging.WARNING, 'error':logging.ERROR } str = str.lower() return level.get(str) path = os.path.join(setting.LOG_PATH,setting.LOG_NAME) #拼好日誌的絕對路徑 utp_log = MyLogger(path,setting.LEVEL).logger #日誌級別 #直接在這裏實例化,用的時候就不用再實例化了
總結:
該自動化框架是基於unittest從新封裝的,也是基於數據驅動進行的,只是數據的格式不是excel而是yaml格式的。與第一篇自動化框架相比,不須要本身寫框架。