原文地址:接口自动化笔记
配置:
在pycharm中安装requests第三方库
打开DOS命令或者在pycharm的terminal中输入pip install requests就可以安装了
安装pyyaml 5.3.1第三方库
打开DOS命令或者在pycharm的terminal中输入pip install pyyaml安装
语法:
- 使用单元测试框架
class (类名):
def setUP(self):
pass
def 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’)
- 只在开始和结束输出,每条用例运行中不再输出
@classmethod
def setUpClass(cls):
print(‘this is start…’)
@classmethod
def tearDownClass(cls):
print(‘this is end…’)
- 断言
**self.assertIn(‘预期结果****’,res.text)**
如果断言结果与实际结果不一致,则会出现下方情况,点击查看差异
左边预期结果,右边实际结果
5. 设置全局变量global
在登录接口中设置一个cookie的全局变量,下边的接口中就可以使用了
global cok
cok=res.cookies
- 导入用例:
先在项目中新建一个Python Package命名为case,然后在其中新建一个后缀为.yaml的文件,
然后在文件中写入用例,格式为:
Url: 网址 #每个参数名的冒号后面要加空格再跟参数值
method: 请求方式
Detil:描述(此项可不写)
data:
参数名: 参数值(不加引号)
check:
- 预期结果(-后有空格)
如:
url: http://192.168.2.110/geeknet/flow.php?step=add_to_cart
method: POST
Detil: 加入购物车
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=cart
method: GET
data:
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.110
port = 3306
user = root
passwd = root
db = gk
charset = utf8
(2)在common文件夹中建一个Python文件configmysql来配置连接数据库
#配置mysql
import pymysql
import configparser
config = 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函数,用来删除用例执行后的脏数据(无用的)
@classmethod
def 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 HTMLTestRunner
@ddt.ddt
class Test(unittest.TestCase):
@classmethod
def 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)
@classmethod
def 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 os
import 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文件中的类
from 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**
**主方法**
博客来源:雨夜的博客