接口自动化笔记
配置:
在pycharm中安装requests第三方库
打开DOS命令或者在pycharm的terminal中输入pip install requests就可以安装了
安装pyyaml 5.3.1第三方库
打开DOS命令或者在pycharm的terminal中输入pip install pyyaml安装
语法:
使用单元测试框架
class (类名): def setUP(self): passdef test_01(self): print('this is test01’) def tearDown(self): pass
跳过用例
#如果想要跳过某条用例,只需要在前面加****@unittest.skip**# @unittest.skip #跳过本条用例def test_02(self): print('this is test02’)def test_03(self): print('this is test03’)
只在开始和结束输出,每条用例运行中不再输出
@classmethoddef setUpClass(cls): print('this is start…’)@classmethoddef tearDownClass(cls): print('this is end…’)
断言
**self.assertIn('预期结果****’,res.text)**
如果断言结果与实际结果不一致,则会出现下方情况,点击查看差异 左边预期结果,右边实际结果
设置全局变量global 在登录接口中设置一个cookie的全局变量,下边的接口中就可以使用了
global cokcok=res.cookies
导入用例: 先在项目中新建一个Python Package命名为case,然后在其中新建一个后缀为.yaml的文件, 然后在文件中写入用例,格式为:
Url: 网址 #每个参数名的冒号后面要加空格再跟参数值method: 请求方式Detil:描述(此项可不写)data: 参数名: 参数值(不加引号)check:
预期结果(-后有空格) 如:
url: http://192.168.2.110/geeknet/flow.php?step=add_to_cartmethod: POSTDetil: 加入购物车data: goods: '{“quick”:1,”spec”:[],”goods_id”:62,”number”:”1”,”parent”:0}’check: #预期结果 - one_step_buy-url: http://192.168.2.110/geeknet/flow.php?step=cartmethod: GETdata:check:
购物车( 1 ) 在类前添加@ddt.ddt 然后在需要引入的函数前加@ddt.file_data(r’用例文件存放路径’)如
@ddt.file_data(r’D:\python\jiekou0518\case\api.yaml’)#加r防止路径转移
然后在函数中使用如:
def test_one(self,**test_data):url=test_data.get('url’)
如何连接数据库 (1)新建一个python包config,然后在其中创建一个config.ini文件,向其中写入数据库的连接配置:哪个MySQL连接,主机,端口号,用户名,密码,库名,编码方式:
[MYSQL]host = 192.168.2.110port = 3306user = rootpasswd = rootdb = gkcharset = utf8
(2)在common文件夹中建一个Python文件configmysql来配置连接数据库
#配置 mysqlimport pymysql import config parserconfig = configparser.ConfigParser() #读取配置文件 config.read(r’D:\python\jiekou0518\config\config.ini’) class ApiTools(): #定义函数连接数据库 def conn_mysql(self): host = config.get('MYSQL’,’host’) port = config.get('MYSQL’,’port’) user = config.get('MYSQL’,’user’) passwd = config.get('MYSQL’,’passwd’) db = config.get('MYSQL’,’db’) charset = config.get('MYSQL’,’charset’) self.connect = pymysql.connect( host = host, port = int(port), user = user, passwd = passwd, db = db, charset = charset, ) #连接数据库中的游标cursor,用来执行sql语句 self.cursor = self.connect.cursor()# 定义执行MySQL的函数,不同的场景下有不同的方法def execute_sql(self,sql): '’’ 执行sql语句,包括更新和新增数据 '’’ self.conn_mysql() #连接数据库并获取游标 self.cursor.execute(sql) #用游标去执行sql语句 self.connect.commit() #执行完毕提交def search_sql(self,sql): '’’ 执行查询语句 '’’ self.conn_mysql() self.cursor.execute(sql) return self.cursor.fetchall() #返回所有行的值#定义关闭sql连接的函数,避免占用服务器资源def close_sql(self): '’’ 关闭游标和数据库连接 '’’ self.cursor.close() self.connect.close()#测接口要测幂等,为了防止重复提交if __name__ == '__main__’:too = ApiTools()too.conn_mysql()sql = 'delete from gk_order_info WHERE zipcode =457100;’api = too.execute_sql(sql)too.close_sql()print(api)
最后在runfile文件中新增*tearDownClass*函数,用来删除用例执行后的脏数据(无用的)
@classmethoddef tearDownClass(cls): too = configmysql.ApiTools() too.conn_mysql() sql = “delete from gk_order_info where order_sn in(select o.order_sn from “ “(select order_sn from gk_order_info order by add_time desc limit 1) as o)” too.execute_sql(sql) too.close_sql()
最后将用例打印出报告,使用unittest。*makeSuite(*类名*)*可以将主函数所有的类都添加到测试集合中
if __name__=='__main__’: # unittest.main() su=unittest.TestSuite() #建立测试集合 su.addTest(unittest.makeSuite(Test)) #将主函数中的所有用例都添加进去 now=time.strftime('%Y-%m-%d %H-%M-%S') #使用当前时间并格式化时间为年月日时分秒 filename = r’D:\python\jiekou0518\report\ '+ now +’resuilt.html’ fp=open(filename,’wb’)runner=HTMLTestRunner(stream=fp,title='自动化测试报告’,description='用例描述’) runner.run(su) fp.close()
Runfile文件案例:
import unittest import ddt,time,requests from common import configmysql from HTMLTestRunner import HTMLTest Runner@ddt.ddtclass Test(unittest.TestCase): @classmethoddef setUpClass(cls): #在所有用例执行之前先先执行登录的用例,获取cookies url='http://192.168.2.110/geeknet/user.php’ data={ 'username’:’lee000000’, 'password’:’000000’, 'act’:’act_login’, 'back_act’:’http://192.168.2.110/geeknet/', 'submit’:’’ } res=requests.post(url=url,data=data) cls.assertIn(cls,’欢迎您回来’,res.text) global cok cok=res.cookies@ddt.file_data(r’D:\python\jiekou0518\case\api.yaml’)#加r防止路径转移def test_one(self,**test_data): url=test_data.get('url’) method=test_data.get('method’) detil=test_data.get('detil’) data=test_data.get('data’) check=test_data.get('check’) if method=='GET’: #转化为文本格式,方便后边去断言 res=requests.get(url=url,cookies=cok).text elif method=='POST’: res=requests.post(url=url,data=data,cookies=cok).text # for I in check: # try: # self.assertIn(i,res) # print(i,’用例执行成功’) # except Exception as e: # print(i,’用例执行失败’) for I in check: self.assertIn(i,res)@classmethoddef tearDownClass(cls): too = configmysql.ApiTools() too.conn_mysql() sql = “delete from gk_order_info where order_sn in(select o.order_sn from “ “(select order_sn from gk_order_info order by add_time desc limit 1) as o)” too.execute_sql(sql) too.close_sql() if __name__=='__main__’: # unittest.main() su=unittest.TestSuite() #建立测试集合 su.addTest(unittest.makeSuite(Test)) #将主函数中的所有用例都添加进去 now=time.strftime('%Y-%m-%d %H-%M-%S') #使用当前时间并格式化时间为年月日时分秒 filename = r’D:\python\jiekou0518\report\ '+ now +’resuilt.html’fp=open(filename,’wb’) runner=HTMLTestRunner(stream=fp,title='自动化测试报告’,description='用例描述’) runner.run(su) fp.close()
如何将测试报告通过邮件发送到指定人员 Config.ini 配置mail为163邮箱时,password不是登录密码,只是一个授权码 (1)在config.ini配置文件中新增邮箱配置:
[email]smtpserver = smtp.163.com sender = luokuo8080@163.com password = luokuo8080 receive = luokuo1018@163.com
(2)在common包中新增configmail.py文件。编写发送邮件的代码
import configparser import osimport smtplib from email.mime.text import MIMEText from email.header import Header config = configparser.ConfigParser()config.read(r’D:\python\jiekou0518\config\config.ini’) class Send_mail: #我们需要先将最新的测试报告传到我们的函数中 def send_email(self,new_report): #parm new_report是把找到的最新的测试报告传进来作为邮件内容发送 f = open(new_report,’rb’) body = f.read() f.close() smtpserver = config.get('email','smtpserver') #从config.ini文件中取出email的参数 sender = config.get('email’,’sender’) password = config.get('email’,’password’) receive = config.get('email’,’receive’) subject = 'API TEST 自动化测试报告lee' #定义标题 msg = MIMEText(body,’html’,’utf-8’) msg['from’] = sender msg['to’] = receive msg['subject’] = Header(subject,’utf-8’) smtp = smtplib.SMTP() #实例化smtp(发送邮件的方法) smtp.connect(smtpserver) #连接smtp服务器 smtp.login(sender,password) #登录 smtp.sendmail(sender,receive,msg.as_string()) #发送 smtp.quit() #退出def latest_report(self,report_dir): #:param report_dir:把报告存放的路径传进来,以供筛选最新生成的测试报告 #report_dir:把报告存放的路径传进来 lists = os.listdir(report_dir) #列举report_dir下面的所有文件 结果以列表的形式返回 #对列表进行排序(默认从小到大) lists.sort(key = lambda fn:os.path.getmtime(report_dir + '\\’ +fn)) #os.path.getmtime是获取文件的最后修改时间 #os.path.join路径拼接 file = os.path.join(report_dir,lists[-1]) #即file= 'D:\python\jiekou0518\report\ 2020-05-20 10-46-05resuilt.html' return file if __name__ == '__main__’: mail = Send_mail() report_dir = r’D:\python\jiekou0518\report’ new_report = mail.latest_report(report_dir)mail.send_email(new_report) (3)在runfile中调用发送邮件的函数并将测试报告发送到指定邮箱#先引入configmail文件中的类f rom common.configmail import Send_mail #然后调用 mail = Send_mail() report_dir = r’D:\python\jiekou0518\report’ new_report = mail.latest_report(report_dir) mail.send_email(new_report)
简答说下你们的自动化是如何做的?
我们使用的是用python编写的一个小型的接口自动化 使用的是python+unittest+yaml+request+ddt框架,进行编写的接口自动化脚本。 一般我们会把接口自动化的测试用例按格式放到yaml文件里面 然后把一些固定的配置文件可以放到config.ini文件里面,比如说数据库的IP地址,账号和密码,端口,要连接的数据库的库名等等,如果需要调用config.ini里的配置可以通过实例化configparser把配置文件里面的内容给get进来然后我们会写一些经常用到的工具,放到tools里面,比如说连接数据库的函数,包括提交sql语句和查询语句和关闭数据库连接的函数。把他们放到configmysql文件里面,然后在我们测试的时候我们会把我们的主方法写在runmain.py 这个文件里面,然后在这个文件里面使用request方法重构get和post请求,我们会首先用ddt.file_data把yaml文件路径引入,然后定义一个函数,把测试用例的url,方法和请求参数以及预期结果通过**test_data把数据传进来之后再一个一个给get进来,然后用if语句去判断get请求或者post请求并用request去发送请求,然后用for循环把检查点给循环出来并进行assert断言,并用try方法去处理异常信息,然后执行完毕之后我们可以调用数据库处理的方法去进行数据清理,最后用HtmlTestrunner发送测试报告。
如何测试依赖的接口?
对于依赖的接口我们一般是 把上一个接口的返回值给一个中间变量return出来,并 且把这个变量设置成全局变量,如果下个接口使用直接调用这个全局变量就可以了。
如何测试需要登录的接口?
一般需要登录的接口我们使用的是unittest框架 那么我们就可以把需要登录的接口放到setupclass里面然后把cookie的值给一个 中间变量,然后把中间变量global成全局变量,然后下面的接口如果需要cookie直 接在请求的时候直接把全局变量的cookie传入进去就可以了。
测试用例放在哪?
我们的测试用例是在yaml文件里面管理的,把测试用例维护到yaml文件里面 然后在使用里面的测试用例的时候我们可以用ddt进行数据驱动,用ddt.file_data 把yaml文件的路径引入进来然后用get方法获取yaml文件里面的每个字段的字段名 然后再去构造请求。
接口产生的垃圾数据如何清理?
用python连数据库,做增删改查的操作。测试用例前置操作,用setUp做数据准备比如登录。测试用路后置操作,tearDown连接数据库做数据清理
python如何连接数据库(*mysql*)?
通过导入pymysql包去连接数据库 需要通过configparser用get方法去获取config.ini配置文件里面 的数据库的参数比如:port 、user 、passwd 、db名字、charset 编码方式 然后用pymsql.connet方法把参数传进去去连接数据库获取数据库游标cursor 然后用游标的execute方法去执行sql用commit方法去提交数据,如果是 查询的数据需要通过cursor.fetchall()获取所有数据并把数据return出来, 然后最后关闭游标,关闭连接。
**脚本结构:** **— api.yaml** **存放接口测试用例** **— config.ini** **存放数据库的连接配置** **存放email的连接的配置** **— common** **—configmysql.py** **构造数据库连接的方法** **构造数据库执行(execute_sql)** **/查询(****search_sql****)** **/关闭数据库连接(****close_sql****)** **--configemail.py** **发送邮件** **-- runmain.py** **主方法**