【Python+Request+Pytest】接口自动化测试脚本要点总结

文章结合视频观看效果最好,接口自动化测试视频学习地址:https://www.bilibili.com/video/BV1914y1F7Bv/?

目录:导读

一、框架搭建流程

1. 封装接口请求

2. 存储接口信息

3. 封装登录和其他方法

4. 使用Pytest管理测试用例

5. 添加日志模块

6. 生成测试报告

7. 测试报告发送至邮箱

8. 优化动态数据的存储

9. 项目目录

二、上传代码到github

三、运行测试用例的两种方法

1. 命令行模式

 2. 在python脚本中调用pytest 

四、重构接口自动化测试框架

写在最后


一、框架搭建流程

1. 封装接口请求

封装post和get方法方便在使用requests模块发送请求时,仅调用一个方法即可

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# fileName: run_method.py
import requests


class RunMethod(object):

def post_main(self, url, headers, data):
# 忽略不安全的请求警告信息
requests.packages.urllib3.disable_warnings()
# 遇到requests的ssl验证,若想直接跳过不验证,设置verify=False即可
response = requests.post(url=url, headers=headers, data=data, verify=False)
return response

def get_main(self, url, headers, data=None):
# 忽略不安全的请求警告信息
requests.packages.urllib3.disable_warnings()
response = requests.get(url=url, headers=headers, data=data, verify=False)
return response

def run_main(self, method, url, headers, data=None):
# 忽略不安全的请求警告信息
requests.packages.urllib3.disable_warnings()
requests.adapters.DEFAULT_RETRIES = 5

if method == "Post":
res = self.post_main(url, headers, data)
elif method == "Get":
res = self.get_main(url, headers, data)
# 将响应的的数据以字典数据结构和json数据格式返回
return res.json()

2. 存储接口信息

使用yml文件作为配置文件,存储每一个接口信息,主要包括”接口名称、method、url、data和headers“,以及预期结果”expected“

# fileName: api_config.yml

host: https://XXX.com

login:
name: 【登录】手机号码登录
method: Post
url: /v1/login/
data:
phone_country: 86
phone_number: 1210000000
password: 123456
device_id: XXX
device_name: Iphone8plus
device_pubkey: XXX
headers:
Content-Type: application/x-www-form-urlencoded
Authorization: Basic XXX

asset_main:
name: 【资产】用户资产列表页
method: Get
url: /v2/main/
headers:
Authorization: Bearer
app-version: 4.8.0
device-id: XXX
expected:
success: true

lend:
name: 发送请求
method: Post
url: /v1/lend/
data:
payment_password: 123456
amount: 100
pledge_source: 1
headers:
Content-Type: application/x-www-form-urlencoded
Authorization: Bearer
device-id: XXX
app-version: 4.8.0

3. 封装登录和其他方法

1)登录方法用于获取并存储token,存储至access_token.yml中;

2)参数”api_name“的取值是配置文件api_config.yml中的接口名称,比如:login、asset_main和loan_lend。同样封装了一个类ReadYaml,方法是取配置文件中各接口的”method、url、data、headers和expected“等;

3)除了登录接口,其他接口的headers均需要token值,所以在处理headers时要区分登录接口和其他接口;

4)建议:添加异常处理捕获异常,输出自定义的错误信息。

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# fileName: app_api.py
from common.run_method import RunMethod
from common.read_info import ReadYaml
from common.get_log import get_log
from common.deal_token import write_token
import json


class AllApi(object):
def __init__(self):
self.run = RunMethod()
self.read = ReadYaml()
self.logger = get_log()

# 登录,获取token
def login(self, api_name):
try:
# 获取接口请求参数
method = self.read.get_method(api_name)
url = self.read.get_url(api_name)
data = self.read.get_data(api_name)
headers = self.read.get_headers(api_name)
response = self.run.run_main(method, url, headers, data)

# 把token值写到配置文件access_token.yml中,供其他接口调用
write_token(response)

print(json.dumps(response, indent=2, ensure_ascii=False, sort_keys=False))
return response
except Exception as e:
self.logger.info("接口访问出错啦~ %s" % e)

# 其他接口请求封装
def send_request(self, api_name):
try:
# 获取接口请求参数
method = self.read.get_method(api_name)
url = self.read.get_url(api_name)
headers = self.read.get_headers(api_name)
# 区分Get和Post方法
if method == "Get":
response = self.run.run_main(method, url, headers)
elif method == "Post":
data = self.read.get_data(api_name)
response = self.run.run_main(method, url, headers, data)
# print(json.dumps(response, indent=2, ensure_ascii=False, sort_keys=False))

print(json.dumps(response, indent=2, ensure_ascii=False, sort_keys=False))
print(response["success"])
return response
except Exception as e:
self.logger.info("接口访问出错啦~ %s" % e)

# 获取预期结果,方便断言时直接使用
def get_expect(self, api_name):
try:
# 获取配置文件中的预期结果
expect = self.read.get_expected(api_name)
# print(expect)
return expect
except Exception as e:
self.logger.info("获取预期结果出错啦~ %s" % e)

4. 使用Pytest管理测试用例

1)在执行所有用例之前先执行登录接口,获取token。所以把登录接口的请求放在conftest.py文件中

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# fileName: conftest.py
from API.all_api import AllApi
import pytest
from common.get_log import get_log
logger = get_log()

# 在执行所有用例之前先执行登录接口,获取token
@pytest.fixture(scope="session")
def init_token():
# 正确邮箱/手机号和密码登录
logger.info("\n ============================= 在所有用例执行之前,生成token =============================")
all_login = AllApi()
all_login.login("login_sandbox_phoneNumber")

2) 把每个功能模块封装成一个类,每个用例封装成一个方法。例如资产模块的用例如下:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# fileName: test_asset.py
from API.all_api import AllApi
import pytest
from common.get_log import get_log
logger = get_log()


# 资产模块的测试用例
@pytest.mark.usefixtures("init_token")
class TestAsset(object):
@pytest.fixture(scope="class")
def init_asset(self):
logger.info("\n ==============================【资产】测试用例开始 ==============================")
all_request = AllApi()
return all_request

@pytest.mark.parametrize("api_name", ["asset_main"])
def test_asset_main(self, api_name, init_asset):
print("\n 用例名称:获取资产列表信息\n")
res = init_asset.send_request(api_name)
expected = init_asset.get_expect(api_name)
# 断言1:success的值为true
assert res['success'] == expected['success'], "success的值为: %s" % res['success']


if __name__ == "__main__":
# pytest.main(['-v', 'test_asset.py'])
pytest.main(['-v', 'test_asset.py', '--html=report/asset_report.html', '--self-contained-html'])

5. 添加日志模块

1)使用配置文件配置loggers、handlers和formatters(日志器、处理器和格式器),文件名称是log.conf

[loggers]
keys=root,main
[logger_root]
level=DEBUG
handlers=consoleHandler,fileHandler
[logger_main]
level=DEBUG
qualname=main
handlers=fileHandler
[handlers]
keys=consoleHandler,fileHandler
[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=fmt
args=(sys.stdout,)
[handler_fileHandler]
class=logging.handlers.RotatingFileHandler
level=DEBUG
formatter=fmt
args=('../log/Wallet_API_Test.log','a')
[formatters]
keys=fmt
[formatter_fmt]
format=%(asctime)s - %(filename)s - %(levelname)s - [line:%(lineno)d] - %(message)s

2)使用fileConfig()函数读取日志配置文件

# fileName: get_log.py
import logging.config
import logging


# 读取日志配置文件
def get_log():
con_log = "../configs/log.conf"
logging.config.fileConfig(con_log)
log = logging.getLogger()
return log

6. 生成测试报告

1)安装pytest-html插件。也可以使用allure插件生成测试报告,但是如果pytest版本过高,就无法识别allure插件

2)添加“--self-contained-html”可以整合样式文件到html文档中,方便之后发送测试报告到邮箱

pytest.main(['-v', '--html=report/all_report.html', '--self-contained-html'])

7. 测试报告发送至邮箱

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# fileName: run_email.py
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.header import Header
import smtplib


# 定义发邮件
def send_mail(file_path):

f = open(file_path, 'rb')
mail_body = f.read()
f.close()

smtpserver = 'smtp.qq.com'
# 设置登录邮箱的账号和授权密码
user = '[email protected]'
password = ""
sender = '[email protected]'
# 可添加多个收件人的邮箱
receives = ['[email protected]']
# 构造邮件对象
msg = MIMEMultipart('mixed')
# 定义邮件的标题
subject = '接口自动化测试报告'
# HTML邮件正文,定义成字典
msg['Subject'] = Header(subject, "utf-8")
msg['From'] = sender
msg['To'] = ','.join(receives)
# 构造文字内容
text_plain = MIMEText("附件是最新的接口自动化测试报告,请查看", 'html', 'utf-8')
msg.attach(text_plain)
# 构造附件
text_attr = MIMEText(mail_body, 'base64', 'utf-8')
text_attr["Content-Type"] = 'application/octet-stream'
text_attr['Content-Disposition'] = 'attachment; filename = "test.html"'
msg.attach(text_attr)

# 邮箱设置时勾选了SSL加密连接,进行防垃圾邮件,SSL协议端口号要使用465
smtp = smtplib.SMTP_SSL(smtpserver, 465)
# 向服务器标识用户身份
smtp.helo(smtpserver)
# 向服务器返回确认结果
smtp.ehlo(smtpserver)
# 登录邮箱的账号和授权密码
smtp.login(user, password)

print("开始发送邮件...")
# 开始进行邮件的发送,msg表示已定义的字典
smtp.sendmail(sender, receives, msg.as_string())
smtp.quit()
print("已发送邮件")


if __name__ == "__main__":
report = "../testcase/report/report.html"
send_mail(report)

  

8. 优化动态数据的存储

把多个登录账号信息等动态数据放到excel表格中,使用xrld和xlutils库对表格进行读取和写入。利用excel存储测试数据,实现测试数据和测试脚本的分离,方便测试数据的维护

9. 项目目录

一直在更新中,文件名可能与其他地方不一致

  

二、上传代码到github

1. 创建git仓库:进入项目的根目录,比如项目名是:Test,则进入Test文件夹下

命令:git init

2. 将项目内所有文件添加至仓库中

命令:git add .

3. commit到仓库

命令:git commit -m '首次提交'

4. 到github上创建Repositories后,复制仓库的地址,比如:https://github.com/XXX/Test.git

5. 将本地仓库关联到github上(很重要)

命令:git remote add origin https://github.com/XXX/Test.git

6. 上传代码到github远程仓库:其中-u是把本地master分支和远程master分支关联起来,以后再push时不需要加上-u

命令:git push -u origin master

  7. 若再次上传,则要执行这三步:

1)把Test中的文件都添加进来:git add .

2)提交暂存区的文件,其中message是简要说明这次提交的信息:git commit -m "message"

3)把本地文件推送到github上(有时候需要输入github账号和密码): git push origin master

  8. git常用命令,可参考文章git常用命令结合若干个使用场景

9. 项目git地址:(备注:代码写的不够专业,一直在优化改进中。有兴趣的可以一起讨论)

https://github.com/ChangYixue/Test.git

三、运行测试用例的两种方法

1. 命令行模式

1)先进入测试用例文件所在目录,然后使用“pytest”命令执行该目录下所有的测试用例文件;

2)也可以指定某一个测试用例文件,直接在pytest后面加上文件名称即可,比如“pytest test_asset.py”

3)执行”某文件下的类中所有用例方法“或者”某方法“,分别用命令”pytest 文件名::类名“和”pytest 文件名::类名::方法名“

 2. 在python脚本中调用pytest 

if __name__ == "__main__":
# 若存在多个标记,则用or连接,形成一个测试集,比如'-m=assetList or test or allLists'
pytest.main(['-v', 'test_asset.py', '-m=test'])

四、重构接口自动化测试框架

1. 背景:公司开发人员帮忙重构了脚本,使配置测试环境、维护测试数据、取接口信息和处理接口依赖等更加灵活

2. 重构后的框架简介请待更新。。。

未完待续......

写在最后

如果你觉得文章还不错,请大家 点赞、分享、留言 下,因为这将是我持续输出更多优质文章的最强动力!

看到这篇文章的人有觉得我的理解有误的地方,也欢迎评论和探讨~

你也可以加入下方的的群聊去和同行大神交流切磋

 

猜你喜欢

转载自blog.csdn.net/weixin_67553250/article/details/129504240