接口自动化
代码1
python
class TestClass:
access_token=""
csrf_token=""
sess = requests.Session()
def test1(self):
url="https://api.weixin.qq.com/cgi-bin/token"
datas = {
"grant_type": "client_credential",
"appid": "wx74a8627810cfa308",
"secret": "e40a02f9d79a8097df497e6aaf93ab80"
}
res = requests.get(url=url, params=datas)
print("res的值是:",res.json())
#提取access_token
result = res.json()
value= jsonpath.jsonpath(result, '$.access_token')
TestClass.access_token = value[0]
print("value的值是:",value[0])
def test1(self):
定义方法:定义一个名为 test1 的方法,通常在类中使用,self 表示实例自身。
url="https://api.weixin.qq.com/cgi-bin/token"
定义URL:设置一个变量 url,它存储了要请求的微信 API 的地址,用于获取访问令牌(access_token)。
datas = {
"grant_type": "client_credential",
"appid": "wx74a8627810cfa308",
"secret": "e40a02f9d79a8097df497e6aaf93ab80"
}
定义请求参数:创建一个字典 datas,其中包含了请求所需的参数:
grant_type: 授权类型,这里为 "client_credential"。
appid: 微信公众平台的应用 ID。
secret: 应用的密钥。
res = requests.get(url=url, params=datas)
发送GET请求:使用 requests 库发送一个 GET 请求到指定的 URL,附带前面定义的参数 datas。返回的响应被存储在变量 res 中。
print("res的值是:",res.json())
打印响应内容:将响应的 JSON 格式数据打印出来。res.json() 方法将返回的响应体解析为 Python 字典。
#提取access_token
注释:这行是对下一行代码的说明,表明要从响应中提取访问令牌。
result = res.json()
再次解析响应:将响应的 JSON 数据解析并赋值给变量 result,方便后续操作。
value= jsonpath.jsonpath(result, '$.access_token')
提取 access_token:使用 jsonpath 库从 result 中提取 access_token 的值,'$.access_token' 是 JSONPath 表达式,用于定位 JSON 数据中的 access_token 字段。提取的结果存储在 value 列表中。
TestClass.access_token = value[0]
保存 access_token:将提取到的 access_token 赋值给 TestClass 类的静态属性 access_token。假设 TestClass 是一个定义好的类。
print("value的值是:",value[0])
打印 access_token:打印提取到的 access_token 的值,以便验证是否成功获取。
总结
这段代码的主要功能是向微信 API 请求访问令牌,并处理响应数据以提取和保存 access_token。
代码2
python
def test_createtag(self):
url="https://api.weixin.qq.com/cgi-bin/tags/create?access_token="+TestClass.access_token
datas = {
"tag":{"name":"广西"}
}
res = requests.post(url=url, json=datas)
print(res.json())
def test_createtag(self):
定义方法:定义一个名为 test_createtag 的方法,通常在类中使用,self 表示实例自身。
url="https://api.weixin.qq.com/cgi-bin/tags/create?access_token="+TestClass.access_token
定义URL:设置一个变量 url,它存储了要请求的微信 API 地址,用于创建标签。通过字符串连接,将 TestClass 类中的 access_token 附加到 URL 中,确保请求能够通过身份验证。
datas = {
"tag": {"name": "广西"}
}
定义请求数据:创建一个字典 datas,它包含了要发送的 JSON 数据。这里定义了一个标签对象,其中 name 字段的值为 "广西"。
res = requests.post(url=url, json=datas)
发送POST请求:使用 requests 库发送一个 POST 请求到指定的 URL。请求体使用前面定义的 datas 字典作为 JSON 数据。响应结果被存储在变量 res 中。
print(res.json())
打印响应内容:将响应的 JSON 格式数据打印出来。res.json() 方法将返回的响应体解析为 Python 字典,可以方便地查看 API 返回的信息,例如成功创建标签的结果或任何错误信息。
总结
这段代码的主要功能是向微信 API 发送请求以创建一个名为 "广西" 的标签,并处理响应数据以输出结果。
代码3
python
def testfileupload(self):
url="https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token="+TestClass.access_token
datas = {"media": open("D:\\Users\\ygl\\Desktop\\583143f57e0538868f01de8f1a15ed4.jpg","rb")}
res = requests.post(url=url, files=datas)
print(res.json())
def testfileupload(self):
定义方法:定义一个名为 testfileupload 的方法,通常在类中使用,self 表示实例自身。
url="https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token="+TestClass.access_token
定义URL:设置一个变量 url,它存储了要请求的微信 API 地址,用于上传图片。通过字符串连接,将 TestClass 类中的 access_token 附加到 URL 中,以确保请求能够通过身份验证。
datas = {"media": open("D:\\Users\\ygl\\Desktop\\583143f57e0538868f01de8f1a15ed4.jpg", "rb")}
定义请求数据:创建一个字典 datas,其中包含要上传的文件。使用 open 函数以二进制模式 ("rb") 打开指定路径的图片文件。media 是字段名称,表示上传的媒体文件。
res = requests.post(url=url, files=datas)
发送POST请求:使用 requests 库发送一个 POST 请求到指定的 URL,files 参数用来传递要上传的文件。响应结果被存储在变量 res 中。
print(res.json())
打印响应内容:将响应的 JSON 格式数据打印出来。res.json() 方法将返回的响应体解析为 Python 字典,便于查看 API 返回的信息,如上传成功的结果或任何错误信息。
总结
这段代码的主要功能是向微信 API 发送请求以上传一张图片,并处理响应数据以输出结果。在上传前,需要确保指定路径的文件存在并且可以访问。
代码4
python
def test_start(self):
url="http://47.107.116.139/phpwind"
res = TestClass.sess.request(method="get",url=url)
print(res.text)
result = res.text
TestClass.csrf_token = re.search('name="csrf_token" value="(.*?)"', result).group(1)
def test_start(self):
定义方法:定义一个名为 test_start 的方法,通常在类中使用,self 表示实例自身。
url="http://47.107.116.139/phpwind"
定义URL:设置一个变量 url,它存储了要请求的地址。在这个例子中,它指向一个具体的服务器地址(可能是一个 web 应用)。
res = TestClass.sess.request(method="get", url=url)
发送GET请求:使用 TestClass 中的 sess 对象发送一个 GET 请求到指定的 URL。响应结果被存储在变量 res 中。这里的 sess 可能是一个会话对象,用于保持请求之间的某些状态(如 cookies)。
print(res.text)
打印响应文本:将请求的响应文本打印出来。res.text 属性包含了从服务器返回的原始 HTML 文本内容,可以用于调试或查看返回的信息。
result = res.text
将响应文本赋值给变量:将响应的文本内容存储到变量 result 中,以便后续处理。
TestClass.csrf_token = re.search('name="csrf_token" value="(.*?)"', result).group(1)
提取CSRF令牌:使用正则表达式 re.search 从 result 中查找名为 csrf_token 的字段。这个表达式匹配 <input type="hidden" name="csrf_token" value="..." /> 结构,提取 value 的内容。如果找到匹配项,调用 group(1) 方法获取第一个捕获组(即 CSRF 令牌的值),并将其赋值给 TestClass.csrf_token,以便在后续请求中使用。
总结
这段代码的主要功能是向指定的 URL 发送 GET 请求,并提取出 CSRF 令牌,以便后续操作使用。首先,它获取页面内容,然后解析出 CSRF 令牌,通常用于防止跨站请求伪造攻击。
代码5
python
def test_login(self):
url="http://47.107.116.139/phpwind/index.php?m=u&c=login&a=dorun"
datas = {
"username":"baili",
"password":"baili123",
"csrf_token":TestClass.csrf_token,
"back_url":"http://47.107.116.139/phpwind",
"invite":""
}
headers = {
"Accept":"application/json, text/javascript, /; q=0.01",
"X-Requested-With":"XMLHttpRequest"
}
res= TestClass.sess.request(method="post",url=url,headers=headers,data=datas)
print(res.json())
def test_login(self):
定义方法:定义一个名为 test_login 的方法,通常在类中使用,self 表示实例自身。
url="http://47.107.116.139/phpwind/index.php?m=u&c=login&a=dorun"
定义URL:设置一个变量 url,它存储了要请求的地址,这个 URL 似乎是用于用户登录的接口。
datas = {
"username": "baili",
"password": "baili123",
"csrf_token": TestClass.csrf_token,
"back_url": "http://47.107.116.139/phpwind",
"invite": ""
}
构建请求数据:创建一个字典 datas,其中包含用户登录所需的参数:
"username": 用户名(这里是 baili)。
"password": 密码(这里是 baili123)。
"csrf_token": 使用之前提取的 CSRF 令牌,以防止跨站请求伪造。
"back_url": 登录成功后重定向的 URL。
"invite": 可能是邀请链接或其他信息,当前为空字符串。
headers = {
"Accept": "application/json, text/javascript, /; q=0.01",
"X-Requested-With": "XMLHttpRequest"
}
构建请求头:创建一个字典 headers,设置请求的头部信息:
"Accept": 指定客户端能接受的内容类型,这里表示接受 JSON 和 JavaScript 响应。
"X-Requested-With": 通常用于标识 AJAX 请求,值为 XMLHttpRequest。
res = TestClass.sess.request(method="post", url=url, headers=headers, data=datas)
发送POST请求:使用 TestClass 中的 sess 对象发送一个 POST 请求到指定的 URL,附带请求头和表单数据。响应结果被存储在变量 res 中。
print(res.json())
打印响应的JSON:将响应的 JSON 内容打印出来。res.json() 方法将响应体解析为 JSON 格式的数据,便于查看服务器返回的信息。
总结
这段代码的主要功能是向指定的登录接口发送 POST 请求,提交用户的登录凭据(用户名、密码和 CSRF 令牌),并输出服务器的响应结果,通常是登录是否成功的信息。
main方法:
python
if __name__ == '__main__':
TestClass().test1()
TestClass().test_tag()
# TestClass().test_createtag()
TestClass().testfileupload()
TestClass().test_start()
TestClass().test_login()
- 注意将request.post,request.get等方法替换为requests.Session().request(method='post'), requests.Session().request(method='get')*
接口自动化测试框架封装之统一请求封装
python
import requests
class RequestUtil:
session = requests.session()
#统一请求封装
def all_send_request(self,**kwargs):
res = RequestUtil.session.request(**kwargs)
print("方法类型:",kwargs['method'])
return res
替换后
python
def test_01(self):
url="https://api.weixin.qq.com/cgi-bin/token"
datas = {
"grant_type": "client_credential",
"appid": "wx74a8627810cfa308",
"secret": "e40a02f9d79a8097df497e6aaf93ab80"
}
res = RequestUtil().all_send_request(method='get',url=url,params=datas)
print("res的值是:",res.json())
#提取access_token
result = res.json()
value= jsonpath.jsonpath(result, '$.access_token')
TestClass.access_token = value[0]
print("value的值是:",value[0])
打印的内容
[100%]方法类型: get
res的值是: {'access_token': '85_w4QsEvgAKMHxdvLTR3r7mSEPrGPu4O6IHsn_G8DtqfRzz8rxR1VbhVGQdzN4MrcbsCUlISSH65Q0gTLDvNC9jlLufXv8jMgKpVTyhGU6MRzi6TZRn1NXBuFuvsERHVcAFAGWK', 'expires_in': 7200}
value的值是: 85_w4QsEvgAKMHxdvLTR3r7mSEPrGPu4O6IHsn_G8DtqfRzz8rxR1VbhVGQdzN4MrcbsCUlISSH65Q0gTLDvNC9jlLufXv8jMgKpVTyhGU6MRzi6TZRn1NXBuFuvsERHVcAFAGWK
引入pytest用例管理
依赖requirements.txt
pytest
pytest-html
pytest-xdist
pytest-ordering
pytest-rerunfailures
pytest-base-url
allure-pytest
安装依赖命令:
pip install -r requirements.txt
运行以上代码方法
方法一:命令行
终端运行 pytest -vs
python
pytest -vs #可以运行以上代码 -v输出更详细的信息 -s输出调试信息
方法二:看不到代码执行结果不好用
根目录下新建run.py文件
python
import pytest
if __name__ == '__main__':
pytest.main()
运行结果如下:
============================= test session starts =============================
platform win32 -- Python 3.7.0, pytest-7.4.4, pluggy-1.2.0
rootdir: D:\PythonFiles\pythonProject\testcases
plugins: allure-pytest-2.13.5, anyio-3.7.1, base-url-2.0.0, html-3.2.0, metadata-3.0.0, ordering-0.6, rerunfailures-13.0, xdist-3.5.0
collected 6 items
test_01.py ...... [100%]
============================== 6 passed in 1.55s ==============================
方法三:结合pytest.ini全局配置文件执行
根目录下新建pytest.ini
python
[pytest]
#命令行参数
addopts = -vs --html=./reports/report.html
#配置执行的用例位置
testpaths = ./testcases
#配置修改默认的模块规则
python_files = test_*.py
#配置修改默认的类规则
python_classes = Test*
#配置修改默认的用例规则
python_functions = test_*
#标记
markers =
smoke: 冒烟测试用例
[pytest]
指定配置段:定义一个名为 pytest 的配置段,pytest 会根据这个段落读取后续的配置项。
#命令行参数
addopts = -vs --html=./reports/report.html
命令行参数:设置 pytest 启动时的默认选项。
-v: 启用详细模式,输出每个测试用例的详细信息。
-s: 允许在测试中使用 print 语句,输出到控制台。
--html=./reports/report.html: 生成测试报告,并将其保存到指定路径(./reports/report.html)。
#配置执行的用例位置
testpaths = ./testcases
用例位置:指定 pytest 查找测试用例的目录,这里是 ./testcases。
#配置修改默认的模块规则
python_files = test_*.py
模块规则:定义匹配测试文件的模式。这里只会识别以 test_ 开头并以 .py 结尾的 Python 文件作为测试模块。
#配置修改默认的类规则
python_classes = Test*
类规则:定义匹配测试类的模式。这里只有以 Test 开头的类会被识别为测试类。
#配置修改默认的用例规则
python_functions = test_*
用例规则:定义匹配测试函数的模式。这里只有以 test_ 开头的函数会被识别为测试用例。
#标记
markers =
smoke: 冒烟测试用例
标记:定义自定义标记,用于对测试用例进行分类。这里定义了一个名为 smoke 的标记,表示这些用例是"冒烟测试用例"。可以在运行测试时使用该标记来选择性地执行特定的测试。
总结
这段 pytest 配置文件用于定义测试运行的基本设置,包括命令行选项、测试用例的位置、文件和类的匹配规则,以及自定义标记。通过这些配置,可以灵活地控制测试的发现和执行方式。
方法二应和方法三中的代码结合一起来使用!!!
配置文件markers使用方法如下:
1.配置文件中加上markers =
smoke: 冒烟测试用例
2.在函数上加注解@pytest.mark.smoke,加上后的代码如下
python
@pytest.mark.smoke
def test_start(self):
url="http://47.107.116.139/phpwind"
res = TestClass.sess.request(method="get",url=url)
print(res.text)
result = res.text
TestClass.csrf_token = re.search('name="csrf_token" value="(.*?)"', result).group(1)
@pytest.mark.smoke
def test_login(self):
url="http://47.107.116.139/phpwind/index.php?m=u&c=login&a=dorun"
datas = {
"username":"baili",
"password":"baili123",
"csrf_token":TestClass.csrf_token,
"back_url":"http://47.107.116.139/phpwind",
"invite":""
}
headers = {
"Accept":"application/json, text/javascript, /; q=0.01",
"X-Requested-With":"XMLHttpRequest"
}
res= TestClass.sess.request(method="post",url=url,headers=headers,data=datas)
print(res.json())
3.配置文件addopts参数加上-m smoke,修改后如下:
python
[pytest]
#命令行参数
#--html=./reports/report.html
addopts = -vs -m smoke
#配置执行的用例位置
testpaths = ./testcases
#配置修改默认的模块规则
python_files = test_*.py
#配置修改默认的类规则
python_classes = Test*
#配置修改默认的用例规则
python_functions = test_*
#标记
markers =
smoke: 冒烟测试用例
修改后运行的部分输出信息如下,显示4个没有被运行
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
================= 2 passed, 4 deselected, 1 warning in 0.43s ==================
只有加上@pytest.mark.smoke注解的函数会被运行
拓展延伸:
python
addopts = -vs -m "smoke or user_manager" #加上@pytest.mark.smoke和@pytest.mark.user_manager的注解的函数都会被运行
pytest的前后置,固件,夹具
python
class TestClass:
access_token=""
csrf_token=""
sess = requests.Session()
def setup_class(self):
print("类请求前:数据库连接")
def teardown_class(self):
print("类请求后:数据库关闭")
def setup_class(self):
定义类级别的设置方法:定义一个名为 setup_class 的方法,通常用于在测试类的所有测试用例执行之前进行一些初始化操作。self 代表当前类的实例。
def teardown_class(self):
定义类级别的清理方法:定义一个名为 teardown_class 的方法,通常用于在测试类的所有测试用例执行之后进行一些清理工作。
总结
setup_class 和 teardown_class 方法分别用于在测试类的开始和结束时执行初始化和清理操作。这种结构有助于确保在多个测试用例之间共享的资源(如数据库连接)能够正确地管理和释放。
python
class TestClass:
access_token=""
csrf_token=""
sess = requests.Session()
def setup(self):
print("类请求前:数据库连接")
def teardown(self):
print("类请求后:数据库关闭")
def setup(self):
定义测试用例的设置方法:定义一个名为 setup 的方法,通常用于在每个测试用例执行之前进行一些初始化操作。self 代表当前类的实例。
def teardown(self):
定义测试用例的清理方法:定义一个名为 teardown 的方法,通常用于在每个测试用例执行之后进行一些清理工作。
总结
setup 和 teardown 方法分别用于在每个测试用例的开始和结束时执行初始化和清理操作。这种结构确保每个测试用例在独立的环境中运行,并且相关的资源(如数据库连接)能够被适当管理和释放。
使用fixtrue固件结合conftest.py文件实现前后置
装饰器:
@pytest.fixtrue(scope="")
scope:function 函数
scope:class 类
scope:module 模块
scope:session 会话
python
@pytest.fixture(scope="function", autouse=False)
def exe_sql():
print("请求之前:查询数据库")
yield
print("请求之后:关闭数据库")
class TestClass:
access_token=""
csrf_token=""
sess = requests.Session()
def test_login(self,exe_sql):
url="http://47.107.116.139/phpwind/index.php?m=u&c=login&a=dorun"
datas = {
"username":"baili",
"password":"baili123",
"csrf_token":TestClass.csrf_token,
"back_url":"http://47.107.116.139/phpwind",
"invite":""
}
headers = {
"Accept":"application/json, text/javascript, /; q=0.01",
"X-Requested-With":"XMLHttpRequest"
}
res= TestClass.sess.request(method="post",url=url,headers=headers,data=datas)
print(res.json())
@pytest.fixture(scope="function", autouse=False)
定义一个测试夹具:使用 @pytest.fixture 装饰器定义一个名为 exe_sql 的测试夹具。scope="function" 表示该夹具的作用域是每个测试函数(即每个测试用例运行一次)。autouse=False 表示该夹具不会自动应用于所有测试,需要在具体的测试中手动使用。
yield
暂停并返回控制权:使用 yield 语句,将控制权返回给调用该夹具的测试用例。在 yield 之前的代码在测试用例执行之前运行,而 yield 之后的代码将在测试用例执行完毕后运行。
exe_sql 是一个 pytest 测试夹具,用于在每个测试用例执行之前和之后分别打印消息,模拟数据库查询和关闭的过程。它通过使用 yield 来分隔准备和清理阶段,确保在每个测试用例执行时都有适当的环境和资源管理。
def test_login(self,exe_sql)为调用exe_sql函数
注意在一个文件中设置的固件fixtrue只能在当前文件起作用,如果希望对所有py文件起作用,那么需要新建conftest.py文件
python
import pytest
@pytest.fixture(scope="class", autouse=True)
def exe_sql():
print("请求之前:查询数据库")
yield
print("请求之后:关闭数据库")
params的使用
python
import pytest
@pytest.fixture(scope="session", autouse=False, params=[["baili","baili123"],["baidu","baidu123"]])
def exe_sql(request):
print("请求之前:查询数据库")
yield request.param
print("请求之后:关闭数据库")
@pytest.fixture(scope="session", autouse=False, params=[["baili","baili123"],["baidu","baidu123"]])
定义夹具:这一行使用了 @pytest.fixture 装饰器来定义一个名为 exe_sql 的夹具(fixture)。
scope="session":定义夹具的作用域为 "session",这意味着在整个测试会话中只会创建一次这个夹具。所有测试都将共享这个夹具的实例。
autouse=False:表示这个夹具不会自动使用。你必须在测试函数中显式地使用它。如果设置为 True,则所有测试都会自动使用这个夹具。
params=[["baili","baili123"],["baidu","baidu123"]]:定义了一个参数列表,夹具将会被多次调用,每次调用时使用不同的参数。在这里,它会传递两个参数集:["baili","baili123"] 和 ["baidu","baidu123"]。
def exe_sql(request):
定义夹具函数:定义了 exe_sql 函数,这个函数负责实现夹具的逻辑。request 参数是 pytest 提供的上下文对象,允许你访问夹具的参数和其他信息。
yield request.param
返回参数:使用 yield 语句返回当前的参数集(即 request.param)。当测试函数调用这个夹具时,测试将接收到这个参数。
yield 之后的代码将在测试完成后执行,用于清理资源。
总结
这个夹具 exe_sql 定义了一个会话范围的数据库连接(或类似的资源),用于多个测试的参数化。各个测试通过调用此夹具获取不同的用户凭据,并在测试开始前进行初始化和结束后的清理工作。
python
@pytest.mark.smoke
def test_login(self,exe_sql):#调用exe_sql
print("++++++++++++++++++++++++++++++++++++++++++++++++++++++++",exe_sql)
url="http://47.107.116.139/phpwind/index.php?m=u&c=login&a=dorun"
datas = {
"username":"baili",
"password":"baili123",
"csrf_token":TestClass.csrf_token,
"back_url":"http://47.107.116.139/phpwind",
"invite":""
}
headers = {
"Accept":"application/json, text/javascript, /; q=0.01",
"X-Requested-With":"XMLHttpRequest"
}
res= TestClass.sess.request(method="post",url=url,headers=headers,data=datas)
print(res.json())
部分运行结果:
test_01.py::TestClass::test_login[exe_sql0] 请求之前:查询数据库
++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ['baili', 'baili123']
{'referer': '', 'refresh': False, 'state': 'fail', 'message': ['帐号或密码错误,您还可以尝试1次'], '__error': ''}
PASSED
test_01.py::TestClass::test_login[exe_sql1] 请求之后:关闭数据库
请求之前:查询数据库
++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ['baidu', 'baidu123']
{'referer': '', 'refresh': False, 'state': 'fail', 'message': ['已经连续5次帐号或密码错误,您将在30分钟内无法正常登录'], '__error': ''}
PASSED
test_02.py::Test02::test_02 测试02
PASSED请求之后:关闭数据库