Unittest框架+ddt数据驱动+HTMLTestRunner+sendmail(自动发送测试报告)+git+Jenkins

本次写的是针对有代码基础的,没基础建议先去学基础,以下所有描述内容都是我已经在公司项目实践成功的!仅供参考

整体思路:
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 r
100 
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数据复制到excel2
12 
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.sheetnames
22 
23     sheets2=wb2.sheetnames
24 
25     sheet1=wb1[sheets1[0]]
26 
27     sheet2=wb2[sheets2[0]]
28 
29     maxrow=sheet1.max_row
30 
31     maxcolum=sheet1.max_column
32 
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].value
42 
43             sheet2[i]=cell1
44 
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=filename
56 
57         self.wb=load_workbook(self.filename)
58 
59 #激活sheet
60 
61         self.ws=self.wb.active
62 
63     def write(self,row_n,col_n,value):
64 
65         self.ws.cell(row_n,col_n).value=value
66 
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 = None
19     # 请求头部headers
20     try:
21         # 获取Excel标格中表头为headers的数据
22         headers = eval(testdata["headers"])
23         print("请求头部:%s" % headers)
24     except:
25         headers = None
26 
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数据还是json
43     if type == "json":
44             #json.dumps将字典数据转成json格式,因为不同的接口传递参数是不同的,有的是传data,有的传json
45             body= json.dumps(bodydata)
46     elif type == "data":
47             body = bodydata
48     else:
49             body = bodydata
50 
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 = False
56     res = {}   # 接受返回数据
57 
58     try:
59         r = s.request(method=method,
60                       url=url,
61                       params=params,
62                       headers=headers,
63                       data=body,
64                       verify=verify
65                        )
66         print("页面返回信息:%s" % r.json())
67         res['id'] = testdata['id']
68         res['rowNum'] = testdata['rowNum']
69         res["statuscode"] = str(r.status_code)  # 状态码转成str
70         res["text"] = r.json()
71         res["times"] = str(r.elapsed.total_seconds())   # 接口请求时间转str
72         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 res
84     except Exception as msg:
85         res["msg"] = str(msg)
86         return res
87 #将运行返回的结果,根据自己需要,需要要哪些结果就把哪些结果写入拷贝的那份Excel中
88 def wirte_result(result, filename="D:\Business_ManageMent\Case\\result.xlsx"):
89     # 返回结果的行数row_nub
90     row_nub = result['rowNum']
91     # 写入statuscode
92     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 还是fail
97     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 MIMEApplication
10 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,os
18 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']=now
40                 #添加附件
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,copy
10 
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 #表格中打开的case
24 case=cases[0]
25 #表格中关闭的case
26 case_mobile=cases[1]
27 
28 
29 @ddt.ddt
30 class Test_api(unittest.TestCase):
31       u'''B2C-API'''
32       @classmethod
33       def setUpClass(cls):
34           # 如果有登录的话,就在这里先登录了
35           cls.s = requests.Session()
36           # 复制xlsx
37           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         #检查点 checkpoint
46         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 MIMEText
10 from  Commons.send_mail_report import Send
11
12 #定义一个当前时间戳
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实战做项目,欢迎关注

 

转载于:https://www.cnblogs.com/lz-tester/p/9020664.html

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1.将 HTMLTestRunner.py 放置在 C:\Python36\Lib 下 2.涉及到创建目录和时间,需要在脚本开头 import os import time 3.执行脚本中删除语句 unittest.main() ,一般在脚本最后,然后添加如下语句: #导入HTMLTestRunner库,这句也可以放在脚本开头 from HTMLTestRunner import HTMLTestRunner #定义脚本标题,加u为了防止中文乱码 report_title = u'登陆模块测试报告' #定义脚本内容,加u为了防止中文乱码 desc = u'手机JPG登陆模块测试报告详情:' #定义date为日期,time为时间 date=time.strftime("%Y%m%d") time=time.strftime("%Y%m%d%H%M%S") #定义path为文件路径,目录级别,可根据实际情况自定义修改 path= 'D:/Python_test/'+ date +"/login/"+time+"/" #定义报告文件路径和名字,路径为前面定义的path,名字为report(可自定义),格式为.html report_path = path+"report.html" #判断是否定义的路径目录存在,不能存在则创建 if not os.path.exists(path): os.makedirs(path) else: pass #定义一个测试容器 testsuite = unittest.TestSuite() #将测试用例添加到容器 testsuite.addTest(测试类名("测试方法名1")) testsuite.addTest(测试类名("测试方法名2")) #将运行结果保存到report,名字为定义的路径和文件名,运行脚本 with open(report_path, 'wb') as report: runner = HTMLTestRunner(stream=report, title=report_title, description=desc) runner.run(testsuite) #关闭report,脚本结束 report.close()
### 回答1: Python的unittest库提供了一种基于单元测试测试框架,是一个方便易用的Python测试框架。使用unittest库进行接口自动测试可以提高测试效率和质量,本文将分享如何使用Python unittest库搭建接口自动测试框架。 第一步:安装Python unittest库 首先需要安装Python unittest库,Python unittest库是默认安装在Python中的,无需单独安装。 第二步:安装requests模块 接口自动测试需要使用requests模块来发送HTTP请求、获取响应等操作,因此需要安装requests模块。使用pip安装requests命令如下: pip install requests 第三步:编写测试用例 使用unittest框架编写测试用例,首先需要导入unittest库并创建测试类,编写测试方法,方法名必须以test开头,并使用assert断言方法进行验证。例如: import unittest import requests class TestApi(unittest.TestCase): def test_get_users(self): url = 'http://localhost:8080/api/users' res = requests.get(url) self.assertEqual(res.status_code, 200) self.assertIsNotNone(res.json()) 第四步:执行测试用例 使用unittest框架执行测试用例,使用unittest.main()方法运行所有测试用例。例如: if __name__ == '__main__': unittest.main() 执行测试用例后,将输出测试结果,包括测试用例总数、成功数、失败数等。 第五步:持续集成 持续集成可以帮助实现自动测试,可以将上述步骤集成到自动测试框架中,提高测试效率和质量。使用持续集成工具,例如Jenkins,可以实现自动测试的调度和执行,定期输出测试报告,是测试自动化化的不二选择。 在以上步骤中,请求地址和验证方法需要根据具体需求进行更改,但是编写测试用例的方法是类似的,熟练掌握unittest库可以快速搭建接口自动测试框架,提高测试效率和质量。 ### 回答2: Python unittest requests 接口自动测试框架搭建教程博客是指一篇博客文章,介绍如何使用Python unittest与requests库搭建接口自动测试框架。该教程博客有如下几个方面: 1. 简单介绍Python unittest与requests库,以及它们在接口自动测试中的使用; 2. 详细讲解如何安装Python unittest和requests库,并编写测试用例; 3. 讲解如何通过使用Python unittest的setUp()和tearDown()方法,在测试用例执行前后进行一些操作,以便更好地进行测试; 4. 介绍如何运行测试用例,并查看测试结果,以及如何进行测试报告生成; 5. 提供一些实例,展示如何使用Python unittest与requests库搭建接口自动测试框架。 通过这篇教程博客,读者可以学习如何使用Python unittest与requests库搭建接口自动测试框架,并且能够快速了解并掌握这种接口自动测试方法的流程和基本方法。此外,该教程博客也提供一些实例,帮助读者更好地理解和应用这种方法。因此,这篇教程博客对于想要学习接口自动测试以及深入了解Python unittest和requests库的读者来说,是一篇非常有价值的文章。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值