python?requests實(shí)現(xiàn)上傳excel數(shù)據(jù)流
requests上傳excel數(shù)據(jù)流
headers=self.headers #獲取導(dǎo)入模版 file_home = self.import_template log.info(file_home) wb = load_workbook(filename=file_home) ws = wb['sheet1'] # 修改產(chǎn)廢單位名稱,以及備注 ws['b3'] = 'itest產(chǎn)廢單位'+self.dic["t"] ws['s3'] = 'i原料銷售'+self.dic["t"] wb.save(file_home) url=self.url_1+"/companies/import?companyType=2" payload={} m=MultipartEncoder( fields={ "parent_dir":'/', "name":'file', "filename":'name.xlsx', 'file':('name.xlsx',open(file_home,'rb'),'application/vnd.ms-excel') } ) headers['Content-Type']=m.content_type r=requests.post(url,headers=headers,data=m) log.info(r.json())
數(shù)據(jù)驅(qū)動(dòng)之python+requests+excel
數(shù)據(jù)驅(qū)動(dòng)
是根據(jù)數(shù)據(jù)來測(cè)試的,如讀取 excel表中的測(cè)試用例自動(dòng)填寫測(cè)試結(jié)果,發(fā)送測(cè)試報(bào)告包括以下模塊:
- 1.獲取用例
- 2.調(diào)用接口
- 3.校驗(yàn)結(jié)果
- 4.發(fā)送測(cè)試報(bào)告
- 5.異常處理
- 6.日志模塊
1. 首先設(shè)計(jì)好測(cè)試用例
2.建立文件結(jié)構(gòu)
該自動(dòng)化測(cè)試框架命名為:ATP,bin目錄下寫主程序,cases目錄下放測(cè)試用例,conf目錄下放配置文件,lib目錄下放各個(gè)封裝好的模塊,logs目錄下放日志文件,和readme文件。
3.封裝模塊
common.py:封裝讀取excel用例、調(diào)用接口、檢驗(yàn)結(jié)果、寫入報(bào)告這幾個(gè)模塊。
""" 第一步:讀取excel中用例 第二步:根據(jù)用例發(fā)送請(qǐng)求 第三步:校驗(yàn)結(jié)果 第四步:將測(cè)試結(jié)果、返回報(bào)文寫入excel """ import xlrd,requests from xlutils import copy from lib.log import atp_log class OpCase(object): def get_case(self,file_path): cases= [] #定義一個(gè)列表存放所有的cases if file_path.endswith('.xls') or file_path.endswith('.xlsx'): try: book = xlrd.open_workbook(file_path) sheet = book.sheet_by_index(0) for i in range(1,sheet.nrows): row_data = sheet.row_values(i) #獲取的每一行數(shù)據(jù)存到列表row_data cases.append(row_data[4:8]) atp_log.info('共讀取%s條用例'%(len(cases))) self.file_path = file_path #因?yàn)樵摵瘮?shù)已經(jīng)傳了參數(shù)路徑,為方便write_excel引用,在此實(shí)例化 except Exception as e: atp_log.error('[%s]用例獲取失敗,錯(cuò)誤信息:%s'%(file_path,e)) else: atp_log.error('用例文件不合法,%s'%file_path) return cases def my_request(self,url,method,data): data = self.dataToDict(data) try: if method.upper() == 'POST': res = requests.post(url,data).text elif method.uper() == 'GET': res = requests.get(url,params=data).text else: atp_log.warning('該請(qǐng)求方式暫不支持') res = '該請(qǐng)求方式暫不支持' except Exception as e: msg = '【%s】接口調(diào)用失敗,%s'%(url,e) atp_log.error(msg) res = msg return res def dataToDict(self,data): #把數(shù)據(jù)轉(zhuǎn)成字典。 res = {} data = data.split(',') for d in data: # k, v = d.split('=') res[k] = v def check_res(self,res,check): #res:實(shí)際結(jié)果,check:預(yù)期結(jié)果 res = res.replace('": "','=').replace('": ','=') for c in check.split(','): if c not in res: atp_log.info('結(jié)果校驗(yàn)失敗,預(yù)期結(jié)果:【%s】,實(shí)際結(jié)果【%s】'%(c,res)) return '失敗' return '成功' def write_excel(self,case_res): book = xlrd.open_workbook(self.file_path) new_book = copy.copy(book) sheet = new_book.get_sheet(0) row = 1 for case_case in case_res: sheet.write(row,8,case_case[0]) sheet.write(row,9,case_case[1]) row += 1 new_book.save(self.file_path.replace('xlsx','xls'))
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() # 先實(shí)例化一個(gè)logger對(duì)象,先創(chuàng)建一個(gè)辦公室 logger.setLevel(self.get_level(level)) # 設(shè)置日志的級(jí)別 # f1 = logging.FileHandler(filename='a.log',mode='a',encoding='utf-8') #找到寫日志文件的這個(gè)人 c1 = logging.StreamHandler() # 負(fù)責(zé)往控制臺(tái)輸出的 b1 = 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') c1.setFormatter(fmt) b1.setFormatter(fmt) logger.addHandler(c1) logger.addHandler(b1) self.logger = logger def get_level(self,str): level = { 'debug':logging.DEBUG, 'info':logging.INFO, 'warm':logging.WARNING, 'error':logging.ERROR } str = str.lower() return level.get(str) path = os.path.join(setting.LOG_PATH,setting.LOG_NAME) atp_log = Mylogger(path,'debug').logger #直接在這里實(shí)例化,用的時(shí)候不用再實(shí)例化了 #別的地方用的時(shí)候,直接atp_log.warnning('xxxx')
send_mail.py:封裝發(fā)送郵件模塊
import yagmail from conf import setting from lib.log import atp_log def sendmail(title,content,attrs=None): m = yagmail.SMTP(host=setting.MAIL_HOST,user=setting.MAIL_USER, password=setting.MAIL_PASSWRD,smtp_ssl=True) m.send(to=setting.TO, subject=title, contents = content, attachments = attrs) atp_log.info('發(fā)送郵件完成')
4.配置文件
setting.py,配置文件:設(shè)置郵件地址、日志默認(rèn)級(jí)別、用例存放路徑、日志存放路徑、日志文件名
import os BASE_PATH = os.path.dirname( os.path.dirname(os.path.abspath(__file__)) ) #三層目錄定位到ATP目錄 MAIL_HOST = 'smtp.qq.com' MAIL_USER='12*****89@qq.com' MAIL_PASSWRD = 'gjn*****bcgh' TO = [ '12*****9@qq.com' ] LEVEL = 'debug' #設(shè)置日志默認(rèn)級(jí)別 LOG_PATH = os.path.join(BASE_PATH,'logs') #日志文件在logs目錄下 CASE_PATH = os.path.join(BASE_PATH,'cases') #用例文件在cases目錄下 LOG_NAME = 'atp_log' #設(shè)置日志文件名
5.將ATP文件
Mark directory as Sources Root
6.編寫主程序
start.py
import os,sys BASE_PATH = os.path.dirname( os.path.dirname(os.path.abspath(__file__)) ) sys.path.insert(0,BASE_PATH) from lib.common import OpCase from lib.send_mail import sendmail from conf import setting class CaseRun(object): def find_case(self): op = OpCase() for f in os.listdir(setting.CASE_PATH): #每次循環(huán)的時(shí)候讀一個(gè)excel abs_path = os.path.join(setting.CASE_PATH,f) case_list = op.get_case(abs_path) res_list = [] pass_count,fail_count= 0,0 for case in case_list: #循環(huán)每一個(gè)excel里面的所有用例 url,method,req_data,check = case res = op.my_request(url,method,req_data) #調(diào)用完接口返回的結(jié)果 status = op.check_res(res,check) res_list.append([res,status]) if status == '通過': pass_count += 1 else: fail_count += 1 op.write_excel(res_list) msg = ''' xx你好, 本次共運(yùn)行%s條用例,通過%s條,失敗%s條。 '''%(len(res_list),pass_count,fail_count) sendmail('測(cè)試用例運(yùn)行結(jié)果',content=msg,attrs=abs_path) CaseRun().find_case()
OK,數(shù)據(jù)驅(qū)動(dòng)自動(dòng)化測(cè)試框架編寫完成,運(yùn)行 start.py 程序,收到郵件內(nèi)容如下:
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Python中__repr__和__str__區(qū)別詳解
這篇文章主要介紹了Python中__repr__和__str__區(qū)別詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11Python實(shí)現(xiàn)Mysql數(shù)據(jù)庫(kù)連接池實(shí)例詳解
這篇文章主要介紹了Python實(shí)現(xiàn)Mysql數(shù)據(jù)庫(kù)連接池實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-04-04python scrapy簡(jiǎn)單模擬登錄的代碼分析
在本篇文章里小編給大家整理的是一篇關(guān)于python scrapy簡(jiǎn)單模擬登錄的代碼分析,有興趣的朋友們可以學(xué)習(xí)參考下。2021-07-07Iconfont(矢量圖標(biāo))+iconmoon(圖標(biāo)svg互轉(zhuǎn))配合javascript實(shí)現(xiàn)社交分享系統(tǒng)
這篇文章主要介紹了Iconfont(矢量圖標(biāo))+iconmoon(圖標(biāo)svg互轉(zhuǎn))配合javascript實(shí)現(xiàn)社交分享系統(tǒng),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04Python使用微信itchat接口實(shí)現(xiàn)查看自己微信的信息功能詳解
這篇文章主要介紹了Python使用微信itchat接口實(shí)現(xiàn)查看自己微信的信息功能,結(jié)合實(shí)例形式分析了Python微信itchat模塊常見功能與操作技巧,需要的朋友可以參考下2019-08-08