本次写的是针对有代码基础的,没基础建议先去学基础,以下所有描述内容都是我已经在公司项目实践成功的!仅供参考
整体思路:
1、接口自动化用的是Python中unittest框架
2、所有的测试数据用例存放Excel表
3、封装一套读取和写入的Excel方法
4、重写request方法(为了从Excel读取数据后对数据作分析和判断并在测试报告生成相关信息)
5、通过HTMLTestRunner运行测试用例生成网页版报告
6、将自动化脚本放到公司git上,方便其他人员获取你的代码进行编写脚本,后面会具体讲如何获取代码和提交代码(让运维人员给你开通个git账号,自己注册登录就可以了)
7、通过Jenkins构建任务,定时自动运行git上自动化脚本,后面会具体讲如何配置Jenkins
先看看我的接口自动化整个目录结构和每个文件具体是干嘛的:
一、读取表格的代码:
?1 import xlrd,os,copy ?2 ??3 import sys,os ?4 ??5 #这三行代码是解决文件路径问题 ?6 ??7 curPath = os.path.abspath(os.path.dirname(__file__)) ?8 ??9 rootPath = os.path.split(curPath)[0] 10 ?11 sys.path.append(rootPath) 12 ?13 class ExcelUtil(): 14 ?15 ????list=[] 16 ?17 ????list1 = [] 18 ?19 ????def __init__(self,excelpath,sheetname=‘Sheet1‘): 20 ?21 ????????self.data=xlrd.open_workbook(excelpath) 22 ?23 ????????self.table=self.data.sheet_by_name(sheetname) 24 ?25 ????????#获取第一行作为key值 26 ?27 ????????self.keys=self.table.row_values(0) 28 ?29 ????????#获取总行数 30 ?31 ????????self.rowNum=self.table.nrows 32 ?33 ????????#获取总列数 34 ?35 ????????self.colNum=self.table.ncols 36 ?37 ????????38 ?39 ????#此方法有俩个用处:1、获取关闭或打开的case 2、不同模块的用例也可以通过该方法区分开来 40 ?41 ????def open_case(self): 42 ?43 ????????exceldata = ExcelUtil(os.path.abspath(rootPath+‘/Case/Ddt_case_api/TestCase.xlsx‘), ‘Sheet1‘) 44 ?45 ????????list = [] 46 ?47 ????????list1 = [] 48 ?49 ????????list2=[] 50 ?51 ????????for i in exceldata.dict_data(): 52 ?53 ????????????a = i[‘control_case‘] ?# 这是在Excel加的开关case的字段 54 ?55 ????????????if a == ‘‘: 56 ?57 ????????????????list.append(i) 58 ?59 ????????????elif a==‘mobile_请先登录‘: 60 ?61 ????????????????list1.append(i) 62 ?63 ????????????elif a==‘B_请先登录‘: 64 ?65 ????????????????list2.append(i) 66 ?67 ????????return ?list,list1,list2 68 ?69 ????????# print(len(list)) 70 ?71 ????def dict_data(self): 72 ?73 ????????if self.rowNum<=1: 74 ?75 ????????????print(‘总行数小于1‘) 76 ?77 ????????else: 78 ?79 ????????????r=[] 80 ?81 ????????????j=1 82 ?83 ????????????for i in range(self.rowNum-1): 84 ?85 ????????????????s={} 86 ?87 ????????????????s[‘rowNum‘]=i+2 88 ?89 ????????????????values=self.table.row_values(j) 90 ?91 ????????????????for x in range(self.colNum): 92 ?93 ????????????????????s[self.keys[x]]=values[x] 94 ?95 ????????????????r.append(s) 96 ?97 ????????????????j+=1 98 ?99 ????????????return r100 101 #通过下面这个入口进行调试102 103 if __name__==‘__main__‘:104 105 ????a=ExcelUtil(‘D:\Business_ManageMent\Case\Ddt_case_api\TestCase.xlsx‘)106 107 ????b=a.open_case()108 109 ????print(b)
二、写入表格代码:
1 from openpyxl import load_workbook 2 ?3 import openpyxl 4 ?5 import xlrd 6 ?7 ??8 ?9 def Copy_excel(exclepath1,excelpath2):10 11 #把excle1数据复制到excel212 13 ????wb2=openpyxl.Workbook()14 15 ????wb2.save(excelpath2)16 17 ????wb1=load_workbook(exclepath1)18 19 ????wb2=load_workbook(excelpath2)20 21 ????sheets1=wb1.sheetnames22 23 ????sheets2=wb2.sheetnames24 25 ????sheet1=wb1[sheets1[0]]26 27 ????sheet2=wb2[sheets2[0]]28 29 ????maxrow=sheet1.max_row30 31 ????maxcolum=sheet1.max_column32 33 ????for m in range(1,maxrow+1):34 35 ????????for n in range(97,97+maxcolum):36 37 ????????????n=chr(n)38 39 ????????????i=‘%s%d‘%(n,m)40 41 ????????????cell1=sheet1[i].value42 43 ????????????sheet2[i]=cell144 45 ????wb2.save(excelpath2)46 47 ????wb1.close()48 49 ????wb2.close()50 51 class Write_excel():52 53 ????def __init__(self,filename):54 55 ????????self.filename=filename56 57 ????????self.wb=load_workbook(self.filename)58 59 #激活sheet60 61 ????????self.ws=self.wb.active62 63 ????def write(self,row_n,col_n,value):64 65 ????????self.ws.cell(row_n,col_n).value=value66 67 ????????self.wb.save(self.filename)68 69 ?70 71 ?72 73 #通过下面入口进行调试74 75 if ?__name__==‘__main__‘:76 77 ????Copy_excel(‘D:\Business_ManageMent\Case\Ddt_case_api\TestCase.xlsx‘,‘D:\Business_ManageMent\Case\\result.xlsx‘)78 79 ????wt=Write_excel(‘D:\Business_ManageMent\Case\\result.xlsx‘)80 81 ????wt.write(1,2,‘hello‘)
三、重写request方法及将接口返回结果根据自己的需要写入拷贝的那张Excel表中
1 import json 2 import requests 3 from Tool_class.read_excel_fz import ExcelUtil 4 from Tool_class.writeexcel_fz import Copy_excel, Write_excel 5 ?6 ?7 def send_requests(s, testdata): 8 ????‘‘‘封装requests请求‘‘‘ 9 ????#获取Excel标格中表头为method的数据10 ????method = testdata["method"]11 ????# 获取Excel标格中表头为url的数据12 ????url = testdata["url"]13 ????try:14 ????????#eval函数可以将读取到的参数内容转化成字典格式15 ????????# 获取Excel标格中表头为params的数据16 ????????params = eval(testdata["params"])17 ????except:18 ????????params = None19 ????# 请求头部headers20 ????try:21 ????????# 获取Excel标格中表头为headers的数据22 ????????headers = eval(testdata["headers"])23 ????????print("请求头部:%s" % headers)24 ????except:25 ????????headers = None26 27 28 ????# post请求body类型29 ????# 获取Excel标格中表头为type的数据30 ????type = testdata["type"]31 ????# 获取Excel标格中表头为id的数据32 ????test_nub = testdata[‘id‘]33 ????print("*******正在执行用例:----- ?%s ?----**********" % test_nub)34 ????print("请求方式:%s, 请求url:%s" % (method, url))35 ????print("请求params:%s" % params)36 ????# post请求body内容37 ????try:38 ????????# 获取Excel标格中表头为body的数据39 ?????????bodydata = eval(testdata["body"])40 ????except:41 ?????????bodydata = {}42 ????# 判断传data数据还是json43 ????if type == "json":44 ????????????#json.dumps将字典数据转成json格式,因为不同的接口传递参数是不同的,有的是传data,有的传json45 ????????????body= json.dumps(bodydata)46 ????elif type == "data":47 ????????????body = bodydata48 ????else:49 ????????????body = bodydata50 51 ????if type==‘json‘:52 ????????print("post请求body类型为:%s ,body内容为:%s" % (type,body))53 ????elif method==‘post‘:54 ????????print("post请求body类型为:%s ,body内容为:%s" % (type,body))55 ????verify = False56 ????res = {} ??# 接受返回数据57 58 ????try:59 ????????r = s.request(method=method,60 ??????????????????????url=url,61 ??????????????????????params=params,62 ??????????????????????headers=headers,63 ??????????????????????data=body,64 ??????????????????????verify=verify65 ???????????????????????)66 ????????print("页面返回信息:%s" % r.json())67 ????????res[‘id‘] = testdata[‘id‘]68 ????????res[‘rowNum‘] = testdata[‘rowNum‘]69 ????????res["statuscode"] = str(r.status_code) ?# 状态码转成str70 ????????res["text"] = r.json()71 ????????res["times"] = str(r.elapsed.total_seconds()) ??# 接口请求时间转str72 ????????if res["statuscode"] != "200":73 ????????????res["error"] = "服务错误,接口未请求成功"74 ????????????res["msg"] = str(res["text"])75 ????????else:76 ????????????res["error"] = ""77 ????????????res["msg"] = ""78 ????????if testdata["checkpoint"] == res["text"][‘msg‘]:79 ????????????res["result"] = "pass"80 ????????????print("用例测试结果: ??%s---->%s" % (test_nub, res["result"]))81 ????????else:82 ????????????res["result"] = "fail"83 ????????return res84 ????except Exception as msg:85 ????????res["msg"] = str(msg)86 ????????return res87 #将运行返回的结果,根据自己需要,需要要哪些结果就把哪些结果写入拷贝的那份Excel中88 def wirte_result(result, filename="D:\Business_ManageMent\Case\\result.xlsx"):89 ????# 返回结果的行数row_nub90 ????row_nub = result[‘rowNum‘]91 ????# 写入statuscode92 ????wt = Write_excel(filename)93 ????wt.write(row_nub, 7, result[‘statuscode‘]) ???????# 写入返回状态码statuscode,第8列94 ????wt.write(row_nub, 12, result[‘times‘]) ????????????# 耗时95 ????wt.write(row_nub, 14, result[‘error‘]) ???????????# 状态码非200时的返回信息96 ????wt.write(row_nub, 13, result[‘result‘]) ??????????# 测试结果 pass 还是fail97 ????wt.write(row_nub, 15, result[‘msg‘]) ?????????????# 抛异常
四、定义发送邮件和创建测试用例套件
1 import time,os 2 import smtplib 3 import ?unittest 4 from Commons import HTMLTestRunner_jpg 5 from email.header import Header 6 from email.mime.text import MIMEText 7 from email.mime.multipart import MIMEMultipart 8 import email.mime.multipart 9 from email.mime.application import MIMEApplication10 from Case import *11 12 # test_dir = os.path.abspath(os.path.join(os.getcwd(), ".."))13 # now = time.strftime(‘%y_%m_%d %H_%M_%S‘)14 # filename = (os.path.abspath(‘../Report‘) + ‘\\‘ + now + ‘result.html‘)15 # print(filename)16 # fp = open(filename, ‘wb‘)17 import sys,os18 curPath = os.path.abspath(os.path.dirname(__file__))19 rootPath = os.path.split(curPath)[0]20 sys.path.append(rootPath)21 #定义发送邮件22 class Send():23 ????def __init__(self):24 ????????self.flie_dir=rootPath+‘\Report‘25 ????????self.lists = os.listdir(self.flie_dir)26 ????????#将所有的报告按时间从小到大大排序27 ????????self.lists.sort(key=lambda fn: os.path.getmtime(self.flie_dir + ‘\\‘ + fn))28 ????????#取报告集合中最后一个报告即为最新的测试报告29 ????????self.new_file = os.path.join(self.flie_dir, self.lists[-1])30 ????def send_mail(self):31 ????????????????now=time.strftime(‘%y:%m:%d:%H:%M:%S‘)32 ????????????????sender = ‘1063126729@qq.com‘33 ????????????????recever= ‘steve@wemart.cn‘34 ????????????????msg = MIMEMultipart()35 ????????????????content = ‘最新接口测试报告,详情请下载附件查看,生成时间为:%s‘%(now)36 ????????????????txt = email.mime.text.MIMEText(content, ‘plain‘, ‘utf-8‘)37 ????????????????msg.attach(txt)38 ????????????????msg[‘Subject‘]=‘接口自动化测试报告‘39 ????????????????msg[‘date‘]=now40 ????????????????#添加附件41 ????????????????att = MIMEText(open(self.new_file, "rb").read(), "base64", "utf-8")42 ????????????????att["Content-Type"] = "application/octet-stream"43 ????????????????att["Content-Disposition"] = ‘attachment; filename= "Report.html"‘44 ????????????????msg.attach(att)45 ????????????????server=smtplib.SMTP_SSL(port=465)46 ????????????????server.connect(‘smtp.qq.com‘)47 ????????????????server.login(‘1063126729@qq.com‘,‘lhrcqszwzqafbcjf‘)48 ????????????????server.sendmail(sender,recever,msg.as_string())49 ????????????????server.quit()50 ????????????????print(‘邮件已发送‘)51 ????#创建一个测试套件,将所有的用例添加到测试套件52 ????def creatsuit(slef):53 ????????????test_dir =rootPath+‘\Case‘54 ????????????suit=unittest.TestSuite()55 ????????????discover=unittest.defaultTestLoader.discover(test_dir,pattern=‘test*.py‘,top_level_dir=None)56 ????????????for test_suit in discover:57 ????????????????for case in test_suit:58 ????????????????????suit.addTest(case)59 ????????????return suit
这里说明一下,excel表格自己新建一份,名字命名好,表头各个字段自己喜欢命名啥就命名啥,但注意代码中涉及到表头字段的也要相应调整,保持俩者一致。下面我贴出我存放用例的excel表格样式,供参考:
A:控制开关case B:case名称 C:接口请求方法 D:接口地址 E:传参类型 F:请求头 G:状态码 H:检查点 I:get请求是传的参数 J:post请求时传的参数 K可以不要,这是我当时调试用的
L:接口响应时间 M:运行结果失败获成功 N:提示接口报错 O:接口返回的报错信息 其中G、L、M、N、O是不用填写的,这是为了复制该份表格时,要写入数据到复制的那份表格中用的
五、前四部分都是一些封装的东西,都是为了第五部分调用准备的,下面的代码是利用unittest框架去组织测试用例,因为我通过ddt数据驱动的,所以这部分代码就比较简洁了,如果你把测试数据都写在代码中,这是不利于维护的,看上去也很繁琐,几千条测试用例那要写多少
1 import unittest 2 import ddt 3 import os 4 import requests 5 from Commons import base_api 6 from Tool_class import read_excel_fz 7 from Tool_class import writeexcel_fz 8 from Case.Hand_code_case.Login_case.Test_stor_login02 import * 9 import os,copy10 11 #获取当前文件位置路径12 curpath = os.path.dirname(os.path.realpath(__file__))13 # 获取TestCase.xlsx路径14 testxlsx = os.path.join(curpath, "TestCase.xlsx")15 #获取curpath位置的上一层目录位置16 report_path = os.path.join(os.path.dirname(curpath))17 #获取测试结果表格的目录位置18 reportxlsx = os.path.join(report_path, "result.xlsx")19 #创建读取表格的对象20 testdata = read_excel_fz.ExcelUtil(testxlsx)21 #获取表格中需要运行的数据或不需要运行的数据22 cases=testdata.open_case()23 #表格中打开的case24 case=cases[0]25 #表格中关闭的case26 case_mobile=cases[1]27 28 29 @ddt.ddt30 class Test_api(unittest.TestCase):31 ??????u‘‘‘B2C-API‘‘‘32 ??????@classmethod33 ??????def setUpClass(cls):34 ??????????# 如果有登录的话,就在这里先登录了35 ??????????cls.s = requests.Session()36 ??????????# 复制xlsx37 ??????????writeexcel_fz.Copy_excel(testxlsx, reportxlsx)38 39 ??????#采用装饰器,在运行case之前都会先运行这个,这里的case是表格里打开的用例,也就是我需要运行的数据40 ??????@ddt.data(*case)41 ??????def test_api_01(self, data):42 ????????#先复制excel数据到Case文件夹下面43 ????????res = base_api.send_requests(self.s, data)44 ????????base_api.wirte_result(res, filename=reportxlsx)45 ????????#检查点 checkpoint46 ????????check = data["checkpoint"]47 ????????print("检查点->:%s"%check)48 ????????#返回结果49 ????????res_text = res["text"]50 ????????print("返回实际结果->:%s"%res_text)51 ????????#将接口返回的结果的键和值取到,通过键是否存在,再利用返回的值去和预期结果做断言52 ????????for m,n in res_text.items():53 ?????????????if m==‘data‘ and m==‘msg‘:54 ??????????????????self.assertTrue(res_text[‘data‘]!=None)55 ??????????????????self.assertTrue(res_text[‘msg‘] == check)56 ?????????????elif ‘data‘ not in m:57 ????????????????????self.assertTrue(res_text[‘msg‘]==check)
六、上面将用例组织好了,接下来就是通过HTMLTestRunner模块运行并生成报告了,注:HTMLTestRunner模块自己去百度下载,可以将内容直接复制,然后在你的工程目录下建一个py文件将内容拷贝进去即可
1 import sys,os 2 curPath = os.path.abspath(os.path.dirname(__file__)) 3 rootPath = os.path.split(curPath)[0] 4 sys.path.append(rootPath) 5 ?6 import ?unittest,time,os 7 from ?Commons import HTMLTestRunner_jpg 8 from email.header import Header 9 from email.mime.text import MIMEText10 from ?Commons.send_mail_report import Send1112 #定义一个当前时间戳13 now = time.strftime(‘%y_%m_%d %H_%M_%S‘)14 #以时间给报告命名,这样就不会重复了15 filename = rootPath+‘\Report‘+‘\\‘+ now + ‘result.html‘16 fp=open(filename,‘wb‘)17 a = Send()18 runner = HTMLTestRunner_jpg.HTMLTestRunner(stream=fp, title=‘测试报告‘, description=‘执行情况:‘)19 runner.run(a.creatsuit())20 fp.close()21 #调用发送邮件的方法22 a.send_mail()
七、Jenkins配置
然后回到任务首页,点击任务后面按钮立即构建,打开控制台即可查看运行记录和结果,如图:
以上所有的步骤已经完成了整个项目的构建,大家针对自己的项目可以拿上面的代码加以修改,其实最重要的是思路和良好的代码基础,我没有针对工具安装进行详细说,这个自己百度!自动化并不难,教程也很多,要学会加以总结并融汇贯通。后期主要跟新我学Python的历程,从基础到高级,再到利用Python实战做项目,欢迎关注
Unittest框架+ddt数据驱动+HTMLTestRunner+sendmail(自动发送测试报告)+git+Jenkins
原文地址:https://www.cnblogs.com/lz-tester/p/9020664.html