接口自动化及正则和Jsonpath提取器的应用

[复制链接]
发表于 2026-1-15 01:18:36 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
  1. class TestClass:
  2.     access_token=""
  3.     csrf_token=""
  4.     sess = requests.Session()
  5.     def test1(self):
  6.         url="https://api.weixin.qq.com/cgi-bin/token"
  7.         datas = {
  8.             "grant_type": "client_credential",
  9.             "appid": "wx74a8627810cfa308",
  10.             "secret": "e40a02f9d79a8097df497e6aaf93ab80"
  11.         }
  12.         res = requests.get(url=url, params=datas)
  13.         print("res的值是:",res.json())
  14.         #提取access_token
  15.         result = res.json()
  16.         value= jsonpath.jsonpath(result, '$.access_token')
  17.         TestClass.access_token = value[0]
  18.         print("value的值是:",value[0])
复制代码
  1. def test1(self):
  2. 定义方法:定义一个名为 test1 的方法,通常在类中使用,self 表示实例自身。
  3.     url="https://api.weixin.qq.com/cgi-bin/token"
  4. 定义URL:设置一个变量 url,它存储了要请求的微信 API 的地址,用于获取访问令牌(access_token)。
  5.     datas = {
  6.         "grant_type": "client_credential",
  7.         "appid": "wx74a8627810cfa308",
  8.         "secret": "e40a02f9d79a8097df497e6aaf93ab80"
  9.     }
  10. 定义请求参数:创建一个字典 datas,其中包含了请求所需的参数:
  11. grant_type: 授权类型,这里为 "client_credential"。
  12. appid: 微信公众平台的应用 ID。
  13. secret: 应用的密钥。
  14.     res = requests.get(url=url, params=datas)
  15. 发送GET请求:使用 requests 库发送一个 GET 请求到指定的 URL,附带前面定义的参数 datas。返回的响应被存储在变量 res 中。
  16.     print("res的值是:",res.json())
  17. 打印响应内容:将响应的 JSON 格式数据打印出来。res.json() 方法将返回的响应体解析为 Python 字典。
  18.     #提取access_token
  19. 注释:这行是对下一行代码的说明,表明要从响应中提取访问令牌。
  20.     result = res.json()
  21. 再次解析响应:将响应的 JSON 数据解析并赋值给变量 result,方便后续操作。
  22.     value= jsonpath.jsonpath(result, '$.access_token')
  23. 提取 access_token:使用 jsonpath 库从 result 中提取 access_token 的值,'$.access_token' 是 JSONPath 表达式,用于定位 JSON 数据中的 access_token 字段。提取的结果存储在 value 列表中。
  24.     TestClass.access_token = value[0]
  25. 保存 access_token:将提取到的 access_token 赋值给 TestClass 类的静态属性 access_token。假设 TestClass 是一个定义好的类。
  26.     print("value的值是:",value[0])
  27. 打印 access_token:打印提取到的 access_token 的值,以便验证是否成功获取。
  28. 总结
  29. 这段代码的主要功能是向微信 API 请求访问令牌,并处理响应数据以提取和保存 access_token。
复制代码
代码2
  1.     def test_createtag(self):
  2.         url="https://api.weixin.qq.com/cgi-bin/tags/create?access_token="+TestClass.access_token
  3.         datas = {
  4.             "tag":{"name":"广西"}
  5.         }
  6.         res = requests.post(url=url, json=datas)
  7.         print(res.json())
复制代码
  1. def test_createtag(self):
  2. 定义方法:定义一个名为 test_createtag 的方法,通常在类中使用,self 表示实例自身。
  3.     url="https://api.weixin.qq.com/cgi-bin/tags/create?access_token="+TestClass.access_token
  4. 定义URL:设置一个变量 url,它存储了要请求的微信 API 地址,用于创建标签。通过字符串连接,将 TestClass 类中的 access_token 附加到 URL 中,确保请求能够通过身份验证。
  5.     datas = {
  6.         "tag": {"name": "广西"}
  7.     }
  8. 定义请求数据:创建一个字典 datas,它包含了要发送的 JSON 数据。这里定义了一个标签对象,其中 name 字段的值为 "广西"。
  9.     res = requests.post(url=url, json=datas)
  10. 发送POST请求:使用 requests 库发送一个 POST 请求到指定的 URL。请求体使用前面定义的 datas 字典作为 JSON 数据。响应结果被存储在变量 res 中。
  11.     print(res.json())
  12. 打印响应内容:将响应的 JSON 格式数据打印出来。res.json() 方法将返回的响应体解析为 Python 字典,可以方便地查看 API 返回的信息,例如成功创建标签的结果或任何错误信息。
  13. 总结
  14. 这段代码的主要功能是向微信 API 发送请求以创建一个名为 "广西" 的标签,并处理响应数据以输出结果。
复制代码
代码3
  1.     def testfileupload(self):
  2.         url="https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token="+TestClass.access_token
  3.         datas = {"media": open("D:\\Users\\ygl\\Desktop\\583143f57e0538868f01de8f1a15ed4.jpg","rb")}
  4.         res = requests.post(url=url, files=datas)
  5.         print(res.json())
复制代码
  1. def testfileupload(self):
  2. 定义方法:定义一个名为 testfileupload 的方法,通常在类中使用,self 表示实例自身。
  3.     url="https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token="+TestClass.access_token
  4. 定义URL:设置一个变量 url,它存储了要请求的微信 API 地址,用于上传图片。通过字符串连接,将 TestClass 类中的 access_token 附加到 URL 中,以确保请求能够通过身份验证。
  5.     datas = {"media": open("D:\\Users\\ygl\\Desktop\\583143f57e0538868f01de8f1a15ed4.jpg", "rb")}
  6. 定义请求数据:创建一个字典 datas,其中包含要上传的文件。使用 open 函数以二进制模式 ("rb") 打开指定路径的图片文件。media 是字段名称,表示上传的媒体文件。
  7.     res = requests.post(url=url, files=datas)
  8. 发送POST请求:使用 requests 库发送一个 POST 请求到指定的 URL,files 参数用来传递要上传的文件。响应结果被存储在变量 res 中。
  9.     print(res.json())
  10. 打印响应内容:将响应的 JSON 格式数据打印出来。res.json() 方法将返回的响应体解析为 Python 字典,便于查看 API 返回的信息,如上传成功的结果或任何错误信息。
  11. 总结
  12. 这段代码的主要功能是向微信 API 发送请求以上传一张图片,并处理响应数据以输出结果。在上传前,需要确保指定路径的文件存在并且可以访问。
复制代码
代码4
  1.     def test_start(self):
  2.         url="http://47.107.116.139/phpwind"
  3.         res = TestClass.sess.request(method="get",url=url)
  4.         print(res.text)
  5.         result = res.text
  6.         TestClass.csrf_token = re.search('name="csrf_token" value="(.*?)"', result).group(1)
复制代码
  1. def test_start(self):
  2. 定义方法:定义一个名为 test_start 的方法,通常在类中使用,self 表示实例自身。
  3.     url="http://47.107.116.139/phpwind"
  4. 定义URL:设置一个变量 url,它存储了要请求的地址。在这个例子中,它指向一个具体的服务器地址(可能是一个 web 应用)。
  5.     res = TestClass.sess.request(method="get", url=url)
  6. 发送GET请求:使用 TestClass 中的 sess 对象发送一个 GET 请求到指定的 URL。响应结果被存储在变量 res 中。这里的 sess 可能是一个会话对象,用于保持请求之间的某些状态(如 cookies)。
  7.     print(res.text)
  8. 打印响应文本:将请求的响应文本打印出来。res.text 属性包含了从服务器返回的原始 HTML 文本内容,可以用于调试或查看返回的信息。
  9.     result = res.text
  10. 将响应文本赋值给变量:将响应的文本内容存储到变量 result 中,以便后续处理。
  11.     TestClass.csrf_token = re.search('name="csrf_token" value="(.*?)"', result).group(1)
  12. 提取CSRF令牌:使用正则表达式 re.search 从 result 中查找名为 csrf_token 的字段。这个表达式匹配 <input type="hidden" name="csrf_token" value="..." /> 结构,提取 value 的内容。如果找到匹配项,调用 group(1) 方法获取第一个捕获组(即 CSRF 令牌的值),并将其赋值给 TestClass.csrf_token,以便在后续请求中使用。
  13. 总结
  14. 这段代码的主要功能是向指定的 URL 发送 GET 请求,并提取出 CSRF 令牌,以便后续操作使用。首先,它获取页面内容,然后解析出 CSRF 令牌,通常用于防止跨站请求伪造攻击。
复制代码
代码5
  1.     def test_login(self):
  2.         url="http://47.107.116.139/phpwind/index.php?m=u&c=login&a=dorun"
  3.         datas = {
  4.             "username":"baili",
  5.             "password":"baili123",
  6.             "csrf_token":TestClass.csrf_token,
  7.             "back_url":"http://47.107.116.139/phpwind",
  8.             "invite":""
  9.         }
  10.         headers = {
  11.             "Accept":"application/json, text/javascript, /; q=0.01",
  12.             "X-Requested-With":"XMLHttpRequest"
  13.         }
  14.         res= TestClass.sess.request(method="post",url=url,headers=headers,data=datas)
  15.         print(res.json())
复制代码
  1. def test_login(self):
  2. 定义方法:定义一个名为 test_login 的方法,通常在类中使用,self 表示实例自身。
  3.     url="http://47.107.116.139/phpwind/index.php?m=u&c=login&a=dorun"
  4. 定义URL:设置一个变量 url,它存储了要请求的地址,这个 URL 似乎是用于用户登录的接口。
  5.     datas = {
  6.         "username": "baili",
  7.         "password": "baili123",
  8.         "csrf_token": TestClass.csrf_token,
  9.         "back_url": "http://47.107.116.139/phpwind",
  10.         "invite": ""
  11.     }
  12. 构建请求数据:创建一个字典 datas,其中包含用户登录所需的参数:
  13. "username": 用户名(这里是 baili)。
  14. "password": 密码(这里是 baili123)。
  15. "csrf_token": 使用之前提取的 CSRF 令牌,以防止跨站请求伪造。
  16. "back_url": 登录成功后重定向的 URL。
  17. "invite": 可能是邀请链接或其他信息,当前为空字符串。
  18.     headers = {
  19.         "Accept": "application/json, text/javascript, /; q=0.01",
  20.         "X-Requested-With": "XMLHttpRequest"
  21.     }
  22. 构建请求头:创建一个字典 headers,设置请求的头部信息:
  23. "Accept": 指定客户端能接受的内容类型,这里表示接受 JSON 和 JavaScript 响应。
  24. "X-Requested-With": 通常用于标识 AJAX 请求,值为 XMLHttpRequest。
  25.     res = TestClass.sess.request(method="post", url=url, headers=headers, data=datas)
  26. 发送POST请求:使用 TestClass 中的 sess 对象发送一个 POST 请求到指定的 URL,附带请求头和表单数据。响应结果被存储在变量 res 中。
  27.     print(res.json())
  28. 打印响应的JSON:将响应的 JSON 内容打印出来。res.json() 方法将响应体解析为 JSON 格式的数据,便于查看服务器返回的信息。
  29. 总结
  30. 这段代码的主要功能是向指定的登录接口发送 POST 请求,提交用户的登录凭据(用户名、密码和 CSRF 令牌),并输出服务器的响应结果,通常是登录是否成功的信息。
复制代码
main方法:
  1. if __name__ == '__main__':
  2.     TestClass().test1()
  3.     TestClass().test_tag()
  4.     # TestClass().test_createtag()
  5.     TestClass().testfileupload()
  6.     TestClass().test_start()
  7.     TestClass().test_login()
复制代码

  • 注意将request.post,request.get等方法更换为requests.Session().request(method=‘post’), requests.Session().request(method=‘get’)*
接口自动化测试框架封装之同一哀求封装
  1. import requests
  2. class RequestUtil:
  3.     session = requests.session()
  4.     #统一请求封装
  5.     def all_send_request(self,**kwargs):
  6.         res = RequestUtil.session.request(**kwargs)
  7.         print("方法类型:",kwargs['method'])
  8.         return res
复制代码
更换后
  1.     def test_01(self):
  2.         url="https://api.weixin.qq.com/cgi-bin/token"
  3.         datas = {
  4.             "grant_type": "client_credential",
  5.             "appid": "wx74a8627810cfa308",
  6.             "secret": "e40a02f9d79a8097df497e6aaf93ab80"
  7.         }
  8.         res = RequestUtil().all_send_request(method='get',url=url,params=datas)
  9.         print("res的值是:",res.json())
  10.         #提取access_token
  11.         result = res.json()
  12.         value= jsonpath.jsonpath(result, '$.access_token')
  13.         TestClass.access_token = value[0]
  14.         print("value的值是:",value[0])
复制代码
打印的内容
  1. [100%]方法类型: get
  2. res的值是: {'access_token': '85_w4QsEvgAKMHxdvLTR3r7mSEPrGPu4O6IHsn_G8DtqfRzz8rxR1VbhVGQdzN4MrcbsCUlISSH65Q0gTLDvNC9jlLufXv8jMgKpVTyhGU6MRzi6TZRn1NXBuFuvsERHVcAFAGWK', 'expires_in': 7200}
  3. value的值是: 85_w4QsEvgAKMHxdvLTR3r7mSEPrGPu4O6IHsn_G8DtqfRzz8rxR1VbhVGQdzN4MrcbsCUlISSH65Q0gTLDvNC9jlLufXv8jMgKpVTyhGU6MRzi6TZRn1NXBuFuvsERHVcAFAGWK
复制代码
引入pytest用例管理
依靠requirements.txt
  1. pytest
  2. pytest-html
  3. pytest-xdist
  4. pytest-ordering
  5. pytest-rerunfailures
  6. pytest-base-url
  7. allure-pytest
复制代码
安装依靠下令:
  1. pip install -r requirements.txt
复制代码
运行以上代码方法
方法一:下令行
终端运行  pytest -vs
  1. pytest -vs #可以运行以上代码 -v输出更详细的信息 -s输出调试信息
复制代码
方法二:看不到代码实验效果欠好用
根目次下新建run.py文件
run.py
  1. import pytest
  2. if __name__ == '__main__':
  3.     pytest.main()
复制代码
运行效果如下:
  1. ============================= test session starts =============================
  2. platform win32 -- Python 3.7.0, pytest-7.4.4, pluggy-1.2.0
  3. rootdir: D:\PythonFiles\pythonProject\testcases
  4. 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
  5. collected 6 items
  6. test_01.py ......                                                        [100%]
  7. ============================== 6 passed in 1.55s ==============================
复制代码
方法三:团结pytest.ini全局设置文件实验
根目次下新建pytest.ini
  1. [pytest]
  2. #命令行参数
  3. addopts = -vs --html=./reports/report.html
  4. #配置执行的用例位置
  5. testpaths = ./testcases
  6. #配置修改默认的模块规则
  7. python_files = test_*.py
  8. #配置修改默认的类规则
  9. python_classes = Test*
  10. #配置修改默认的用例规则
  11. python_functions = test_*
  12. #标记
  13. markers =
  14.     smoke: 冒烟测试用例
复制代码
  1. [pytest]
  2. 指定配置段:定义一个名为 pytest 的配置段,pytest 会根据这个段落读取后续的配置项。
  3. #命令行参数
  4. addopts = -vs --html=./reports/report.html
  5. 命令行参数:设置 pytest 启动时的默认选项。
  6. -v: 启用详细模式,输出每个测试用例的详细信息。
  7. -s: 允许在测试中使用 print 语句,输出到控制台。
  8. --html=./reports/report.html: 生成测试报告,并将其保存到指定路径(./reports/report.html)。
  9. #配置执行的用例位置
  10. testpaths = ./testcases
  11. 用例位置:指定 pytest 查找测试用例的目录,这里是 ./testcases。
  12. #配置修改默认的模块规则
  13. python_files = test_*.py
  14. 模块规则:定义匹配测试文件的模式。这里只会识别以 test_ 开头并以 .py 结尾的 Python 文件作为测试模块。
  15. #配置修改默认的类规则
  16. python_classes = Test*
  17. 类规则:定义匹配测试类的模式。这里只有以 Test 开头的类会被识别为测试类。
  18. #配置修改默认的用例规则
  19. python_functions = test_*
  20. 用例规则:定义匹配测试函数的模式。这里只有以 test_ 开头的函数会被识别为测试用例。
  21. #标记
  22. markers =
  23.     smoke: 冒烟测试用例
  24. 标记:定义自定义标记,用于对测试用例进行分类。这里定义了一个名为 smoke 的标记,表示这些用例是“冒烟测试用例”。可以在运行测试时使用该标记来选择性地执行特定的测试。
  25. 总结
  26. 这段 pytest 配置文件用于定义测试运行的基本设置,包括命令行选项、测试用例的位置、文件和类的匹配规则,以及自定义标记。通过这些配置,可以灵活地控制测试的发现和执行方式。
复制代码
方法二应和方法三中的代码团结一起来使用!!!
设置文件markers使用方法如下:
1.设置文件中加上markers =
smoke: 冒烟测试用例
2.在函数上加注解@pytest.mark.smoke,加上后的代码如下
  1.         @pytest.mark.smoke    def test_start(self):
  2.         url="http://47.107.116.139/phpwind"
  3.         res = TestClass.sess.request(method="get",url=url)
  4.         print(res.text)
  5.         result = res.text
  6.         TestClass.csrf_token = re.search('name="csrf_token" value="(.*?)"', result).group(1)
  7.     @pytest.mark.smoke    def test_login(self):
  8.         url="http://47.107.116.139/phpwind/index.php?m=u&c=login&a=dorun"
  9.         datas = {
  10.             "username":"baili",
  11.             "password":"baili123",
  12.             "csrf_token":TestClass.csrf_token,
  13.             "back_url":"http://47.107.116.139/phpwind",
  14.             "invite":""
  15.         }
  16.         headers = {
  17.             "Accept":"application/json, text/javascript, /; q=0.01",
  18.             "X-Requested-With":"XMLHttpRequest"
  19.         }
  20.         res= TestClass.sess.request(method="post",url=url,headers=headers,data=datas)
  21.         print(res.json())
复制代码
3.设置文件addopts参数加上-m smoke,修改后如下:
  1. [pytest]
  2. #命令行参数
  3. #--html=./reports/report.html
  4. addopts = -vs -m smoke
  5. #配置执行的用例位置
  6. testpaths = ./testcases
  7. #配置修改默认的模块规则
  8. python_files = test_*.py
  9. #配置修改默认的类规则
  10. python_classes = Test*
  11. #配置修改默认的用例规则
  12. python_functions = test_*
  13. #标记
  14. markers =
  15.     smoke: 冒烟测试用例
复制代码
修改后运行的部门输出信息如下,表现4个没有被运行
  1. -- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
  2. ================= 2 passed, 4 deselected, 1 warning in 0.43s ==================
复制代码
只有加上@pytest.mark.smoke注解的函数会被运行
拓展延伸:
  1. addopts = -vs -m "smoke or user_manager"    #加上@pytest.mark.smoke和@pytest.mark.user_manager的注解的函数都会被运行
复制代码
pytest的前后置,固件,夹具
  1. class TestClass:
  2.     access_token=""
  3.     csrf_token=""
  4.     sess = requests.Session()
  5.     def setup_class(self):
  6.         print("类请求前:数据库连接")
  7.     def teardown_class(self):
  8.         print("类请求后:数据库关闭")
复制代码
  1. def setup_class(self):
  2. 定义类级别的设置方法:定义一个名为 setup_class 的方法,通常用于在测试类的所有测试用例执行之前进行一些初始化操作。self 代表当前类的实例。
  3. def teardown_class(self):
  4. 定义类级别的清理方法:定义一个名为 teardown_class 的方法,通常用于在测试类的所有测试用例执行之后进行一些清理工作。
  5.     总结
  6. setup_class 和 teardown_class 方法分别用于在测试类的开始和结束时执行初始化和清理操作。这种结构有助于确保在多个测试用例之间共享的资源(如数据库连接)能够正确地管理和释放。
复制代码
  1. class TestClass:
  2.     access_token=""
  3.     csrf_token=""
  4.     sess = requests.Session()
  5.     def setup(self):
  6.         print("类请求前:数据库连接")
  7.     def teardown(self):
  8.         print("类请求后:数据库关闭")
复制代码
  1. def setup(self):
  2. 定义测试用例的设置方法:定义一个名为 setup 的方法,通常用于在每个测试用例执行之前进行一些初始化操作。self 代表当前类的实例。
  3. def teardown(self):
  4. 定义测试用例的清理方法:定义一个名为 teardown 的方法,通常用于在每个测试用例执行之后进行一些清理工作。
  5. 总结
  6. setup 和 teardown 方法分别用于在每个测试用例的开始和结束时执行初始化和清理操作。这种结构确保每个测试用例在独立的环境中运行,并且相关的资源(如数据库连接)能够被适当管理和释放。
复制代码
使用fixtrue固件团结conftest.py文件实现前后置
装饰器:
@pytest.fixtrue(scope=“”)
scope:function 函数
scope:class      类
scope:module 模块
scope:session 会话
  1. @pytest.fixture(scope="function", autouse=False)
  2. def exe_sql():
  3.     print("请求之前:查询数据库")
  4.     yield
  5.     print("请求之后:关闭数据库")
  6.    
  7. class TestClass:
  8.     access_token=""
  9.     csrf_token=""
  10.     sess = requests.Session()
  11.     def test_login(self,exe_sql):
  12.         url="http://47.107.116.139/phpwind/index.php?m=u&c=login&a=dorun"
  13.         datas = {
  14.             "username":"baili",
  15.             "password":"baili123",
  16.             "csrf_token":TestClass.csrf_token,
  17.             "back_url":"http://47.107.116.139/phpwind",
  18.             "invite":""
  19.         }
  20.         headers = {
  21.             "Accept":"application/json, text/javascript, /; q=0.01",
  22.             "X-Requested-With":"XMLHttpRequest"
  23.         }
  24.         res= TestClass.sess.request(method="post",url=url,headers=headers,data=datas)
  25.         print(res.json())
复制代码
  1. @pytest.fixture(scope="function", autouse=False)
  2. 定义一个测试夹具:使用 @pytest.fixture 装饰器定义一个名为 exe_sql 的测试夹具。scope="function" 表示该夹具的作用域是每个测试函数(即每个测试用例运行一次)。autouse=False 表示该夹具不会自动应用于所有测试,需要在具体的测试中手动使用。
  3. yield
  4. 暂停并返回控制权:使用 yield 语句,将控制权返回给调用该夹具的测试用例。在 yield 之前的代码在测试用例执行之前运行,而 yield 之后的代码将在测试用例执行完毕后运行。
  5. exe_sql 是一个 pytest 测试夹具,用于在每个测试用例执行之前和之后分别打印消息,模拟数据库查询和关闭的过程。它通过使用 yield 来分隔准备和清理阶段,确保在每个测试用例执行时都有适当的环境和资源管理。
  6. def test_login(self,exe_sql)为调用exe_sql函数
复制代码
注意在一个文件中设置的固件fixtrue只能在当前文件起作用,如果渴望对全部py文件起作用,那么须要新建conftest.py文件
conftest.py
  1. import pytest
  2. @pytest.fixture(scope="class", autouse=True)
  3. def exe_sql():
  4.     print("请求之前:查询数据库")
  5.     yield
  6.     print("请求之后:关闭数据库")
复制代码
params的使用
conftest.py
  1. import pytest
  2. @pytest.fixture(scope="session", autouse=False, params=[["baili","baili123"],["baidu","baidu123"]])
  3. def exe_sql(request):
  4.     print("请求之前:查询数据库")
  5.     yield request.param
  6.     print("请求之后:关闭数据库")
复制代码
  1. @pytest.fixture(scope="session", autouse=False, params=[["baili","baili123"],["baidu","baidu123"]])
  2. 定义夹具:这一行使用了 @pytest.fixture 装饰器来定义一个名为 exe_sql 的夹具(fixture)。
  3. scope="session":定义夹具的作用域为 "session",这意味着在整个测试会话中只会创建一次这个夹具。所有测试都将共享这个夹具的实例。
  4. autouse=False:表示这个夹具不会自动使用。你必须在测试函数中显式地使用它。如果设置为 True,则所有测试都会自动使用这个夹具。
  5. params=[["baili","baili123"],["baidu","baidu123"]]:定义了一个参数列表,夹具将会被多次调用,每次调用时使用不同的参数。在这里,它会传递两个参数集:["baili","baili123"] 和 ["baidu","baidu123"]。
  6. def exe_sql(request):
  7. 定义夹具函数:定义了 exe_sql 函数,这个函数负责实现夹具的逻辑。request 参数是 pytest 提供的上下文对象,允许你访问夹具的参数和其他信息。
  8. yield request.param
  9. 返回参数:使用 yield 语句返回当前的参数集(即 request.param)。当测试函数调用这个夹具时,测试将接收到这个参数。
  10. yield 之后的代码将在测试完成后执行,用于清理资源。
  11. 总结
  12. 这个夹具 exe_sql 定义了一个会话范围的数据库连接(或类似的资源),用于多个测试的参数化。各个测试通过调用此夹具获取不同的用户凭据,并在测试开始前进行初始化和结束后的清理工作。
复制代码
  1. @pytest.mark.smoke
  2.     def test_login(self,exe_sql):#调用exe_sql
  3.         print("++++++++++++++++++++++++++++++++++++++++++++++++++++++++",exe_sql)
  4.         url="http://47.107.116.139/phpwind/index.php?m=u&c=login&a=dorun"
  5.         datas = {
  6.             "username":"baili",
  7.             "password":"baili123",
  8.             "csrf_token":TestClass.csrf_token,
  9.             "back_url":"http://47.107.116.139/phpwind",
  10.             "invite":""
  11.         }
  12.         headers = {
  13.             "Accept":"application/json, text/javascript, /; q=0.01",
  14.             "X-Requested-With":"XMLHttpRequest"
  15.         }
  16.         res= TestClass.sess.request(method="post",url=url,headers=headers,data=datas)
  17.         print(res.json())
复制代码
部门运行效果:
  1. test_01.py::TestClass::test_login[exe_sql0] 请求之前:查询数据库
  2. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ['baili', 'baili123']
  3. {'referer': '', 'refresh': False, 'state': 'fail', 'message': ['帐号或密码错误,您还可以尝试1次'], '__error': ''}
  4. PASSED
  5. test_01.py::TestClass::test_login[exe_sql1] 请求之后:关闭数据库
  6. 请求之前:查询数据库
  7. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ['baidu', 'baidu123']
  8. {'referer': '', 'refresh': False, 'state': 'fail', 'message': ['已经连续5次帐号或密码错误,您将在30分钟内无法正常登录'], '__error': ''}
  9. PASSED
  10. test_02.py::Test02::test_02 测试02
  11. PASSED请求之后:关闭数据库
复制代码
接口自动化测试框架封装之通过文件保持中央变量实现接口关联
pytest.ini
  1. [pytest]
  2. #命令行参数
  3. #--html=./reports/report.html
  4. #addopts = -vs -m smoke
  5. addopts = -vs
  6. #配置执行的用例位置
  7. testpaths = ./testcases
  8. #配置修改默认的模块规则
  9. python_files = test_*.py
  10. #配置修改默认的类规则
  11. python_classes = Test*
  12. #配置修改默认的用例规则
  13. python_functions = test_*
  14. #标记
  15. ;markers =
  16. ;    smoke: 冒烟测试用例
复制代码
新建yaml_util.py文件如下
yaml_util.py
  1. import os
  2. import yaml
  3. def write_yaml(data):
  4.     with open(os.getcwd()+"/extract.yaml",encoding='utf-8',mode="a+") as f:
  5.         yaml.dump(data,stream=f,allow_unicode=True)
  6. def read_yaml(key):
  7.     with open(os.getcwd()+"/extract.yaml",encoding='utf-8',mode="r") as f:
  8.         value = yaml.load(f,yaml.FullLoader)
  9.         return value[key]
复制代码
  1. import os
  2. import yaml
  3. 导入模块:
  4. os:用于与操作系统进行交互,处理文件和目录路径。
  5. yaml:用于读取和写入 YAML 格式的数据。
  6. def write_yaml(data):
  7. 定义函数:定义一个名为 write_yaml 的函数,接受一个参数 data。该参数将被写入到 YAML 文件中。
  8.     with open(os.getcwd()+"/extract.yaml", encoding='utf-8', mode="a+") as f:
  9. 打开文件:
  10. os.getcwd():获取当前工作目录的路径。
  11. "/extract.yaml":指定要创建或打开的 YAML 文件名。
  12. encoding='utf-8':指定文件编码为 UTF-8,以支持 Unicode 字符。
  13. mode="a+":以附加模式打开文件(如果文件不存在则创建),允许在文件末尾追加内容。
  14. as f:将打开的文件对象赋值给变量 f,以便后续使用。
  15.         yaml.dump(data, stream=f, allow_unicode=True)
  16. 写入 YAML:
  17. yaml.dump(data, stream=f, allow_unicode=True):将数据 data 转换为 YAML 格式并写入到文件 f 中。
  18. allow_unicode=True:允许在 YAML 中使用 Unicode 字符。
  19. def read_yaml(key):
  20. 定义函数:定义一个名为 read_yaml 的函数,接受一个参数 key。该参数用于从 YAML 文件中读取特定的值。
  21.     with open(os.getcwd()+"/extract.yaml", encoding='utf-8', mode="r") as f:
  22. 打开文件:
  23. 再次使用 os.getcwd() 获取当前工作目录的路径,并打开 extract.yaml 文件。
  24. mode="r":以只读模式打开文件。
  25.         value = yaml.load(f, yaml.FullLoader)
  26. 读取 YAML:
  27. yaml.load(f, yaml.FullLoader):将文件 f 中的 YAML 数据加载为 Python 对象,存储在变量 value 中。
  28. yaml.FullLoader:使用完整加载器来解析 YAML 数据,确保安全性和完整性。
  29.         return value[key]
  30. 返回值:从加载的 YAML 数据中,根据提供的 key 返回对应的值。如果 key 在数据中不存在,将会引发 KeyError。
  31. 总结
  32. 这个代码段包含两个函数:
  33. write_yaml(data):将传入的数据以 YAML 格式写入到 extract.yaml 文件中。
  34. read_yaml(key):从 extract.yaml 文件中读取数据,并根据提供的 key 返回相应的值。
复制代码
根目次下新建extract.yaml,文件内容初始为空
修改测试方法,修改后的代码如下:
关键代码:
  1. datas = {"access_token":value[0]}#写入
  2.         write_yaml(datas)
  3. datas = {
  4.             "access_token": read_yaml("access_token")#读取
  5.         }
复制代码
test_01.py
  1. import reimport jsonpathimport pytestimport requestsfrom request_util import RequestUtilfrom testcases.yaml_util import write_yaml, read_yamlclass TestClass:    access_token=""    csrf_token=""    sess = requests.Session()    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')        datas = {"access_token":value[0]}        write_yaml(datas)        TestClass.access_token = value[0]        print("value的值是:",value[0])    def test_tag(self):        url="https://api.weixin.qq.com/cgi-bin/tags/get"        # datas = {        #     "access_token": TestClass.access_token        # }        datas = {            "access_token": read_yaml("access_token")        }        res = requests.get(url=url, params=datas)        print(res.json())    def test_createtag(self):
  2.         url="https://api.weixin.qq.com/cgi-bin/tags/create?access_token="+TestClass.access_token
  3.         datas = {
  4.             "tag":{"name":"广西"}
  5.         }
  6.         res = requests.post(url=url, json=datas)
  7.         print(res.json())
复制代码
运行后会在extract.yaml中天生access_token值
修改test测试方法的缘故起因:
1.类变量不能跨py文件使用
2.同一管理中央变量
yaml_util.py
  1. import os
  2. import yaml
  3. def write_yaml(data):
  4.     with open(os.getcwd()+"/extract.yaml",encoding='utf-8',mode="a+") as f:
  5.         yaml.dump(data,stream=f,allow_unicode=True)
  6. def read_yaml(key):
  7.     with open(os.getcwd()+"/extract.yaml",encoding='utf-8',mode="r") as f:
  8.         value = yaml.load(f,yaml.FullLoader)
  9.         return value[key]
  10. def clear_yaml():    with open(os.getcwd()+"/extract.yaml",encoding='utf-8',mode="w") as f:        f.truncate()      #打扫yaml文件内容
复制代码
  1. f.truncate():将文件的内容截断到当前位置。在这里,由于文件是以写模式打开的,文件指针在文件开始位置,因此这行代码会清空整个文件的内容。
  2. 总结
  3. clear_yaml 函数的作用是清空 extract.yaml 文件的内容。如果文件不存在,则会创建一个新的空文件。这个函数在需要重置文件内容时非常有用。
复制代码
conftest.py
  1. import pytest
  2. from testcases.yaml_util import clear_yaml
  3. # @pytest.fixture(scope="session", autouse=False, params=[["baili","baili123"],["baidu","baidu123"]])
  4. # def exe_sql(request):
  5. #     print("请求之前:查询数据库")
  6. #     yield request.param
  7. #     print("请求之后:关闭数据库")
  8. @pytest.fixture(scope="session", autouse=True)
  9. def clear():
  10.     clear_yaml()#调用清除方法
复制代码
把数据和业务分离
test_01方法部门代码:
  1.         url="https://api.weixin.qq.com/cgi-bin/token"
  2.         datas = {
  3.             "grant_type": "client_credential",
  4.             "appid": "wx74a8627810cfa308",
  5.             "secret": "e40a02f9d79a8097df497e6aaf93ab80"
  6.         }
  7.         res = RequestUtil().all_send_request(method='get',url=url,params=datas)
复制代码
根据以上代码写test_01.yaml文件
test_01.yaml
  1. -
  2.   feature: 模块
  3.   story: 接口
  4.   title: 用例标题
  5.   request:
  6.     method: get
  7.     url: https://api.weixin.qq.com/cgi-bin/token
  8.     params:
  9.       grant_type: client_credential
  10.       appid: wx74a8627810cfa308
  11.       secret: e40a02f9d79a8097df497e6aaf93ab80
  12.   validate: null
复制代码
在yaml_util.py文件中新增如下代码:
yaml_util.py部门代码:
  1. def read_tests(path):
  2.     with open(path,encoding='utf-8',mode="r") as f:
  3.         value = yaml.load(f,yaml.FullLoader)
  4.         return value
复制代码
在yaml_util.py中添加代码如下:
  1. import yamldef read_tests(path):
  2.     with open(path,encoding='utf-8',mode="r") as f:
  3.         value = yaml.load(f,yaml.FullLoader)
  4.         return value
  5. if __name__ == '__main__':    print(read_tests("./test_01.yaml"))#打印[{'feature': '模块', 'story': '接口', 'title': '用例标题', 'request': {'method': 'get', 'url': 'https://api.weixin.qq.com/cgi-bin/token', 'params': {'grant_type': 'client_credential', 'appid': 'wx74a8627810cfa308', 'secret': 'e40a02f9d79a8097df497e6aaf93ab80'}}, 'validate': None}]历程已竣事,退出代码为 0
复制代码
将test_01方法改写:
加注解: @pytest.mark.parametrize(“casedata”,read_tests(“./test_01.yaml”))
调用:def test_01(self,casedata)
通过casedata取值:
  1.                 method = casedata["request"]["method"]
  2.         url = casedata["request"]["url"]
  3.         datas = casedata["request"]["params"]
复制代码
完备的test_01方法如下:
  1. @pytest.mark.parametrize("casedata",read_tests("./test_01.yaml"))
  2.     def test_01(self,casedata):
  3.         print("+++++++++++++++++++++++++casedata=",casedata)
  4.         method = casedata["request"]["method"]
  5.         url = casedata["request"]["url"]
  6.         datas = casedata["request"]["params"]
  7.         res = RequestUtil().all_send_request(method=method,url=url,params=datas)
  8.         print("res的值是:",res.json())
  9.         #提取access_token
  10.         result = res.json()
  11.         value= jsonpath.jsonpath(result, '$.access_token')
  12.         datas = {"access_token":value[0]}
  13.         write_yaml(datas)
复制代码
运行以上代码输出效果为:
  1. +++++++++++++++++++++++++casedata= {'feature': '模块', 'story': '接口', 'title': '用例标题', 'request': {'method': 'get', 'url': 'https://api.weixin.qq.com/cgi-bin/token', 'params': {'grant_type': 'client_credential', 'appid': 'wx74a8627810cfa308', 'secret': 'e40a02f9d79a8097df497e6aaf93ab80'}}, 'validate': None}
  2. 方法类型: get
  3. res的值是: {'access_token': '85_LN6NORAvcBx84DiYJxPnd-fh0MjSfm2ziLuYbkkqJr9DS4GlNbLYznKeSD-awDm4XDskpn9bZ83F8RckNGakAWGps90em8G5FRW9IcOTPctUqOcT4DsPCymNIoYPXDjAFAJRX', 'expires_in': 7200}
  4. value的值是: 85_LN6NORAvcBx84DiYJxPnd-fh0MjSfm2ziLuYbkkqJr9DS4GlNbLYznKeSD-awDm4XDskpn9bZ83F8RckNGakAWGps90em8G5FRW9IcOTPctUqOcT4DsPCymNIoYPXDjAFAJRX
  5. PASSED
  6. 进程已结束,退出代码为 0
复制代码
将test_01.yaml改写成如下:
  1. -
  2.   feature: 模块
  3.   story: 接口
  4.   title: 用例标题
  5.   request:
  6.     method: get
  7.     url: https://api.weixin.qq.com/cgi-bin/token
  8.     params:
  9.       grant_type: client_credential
  10.       appid: wx74a8627810cfa308
  11.       secret: e40a02f9d79a8097df497e6aaf93ab80
  12.   validate: null
  13. -  feature: 模块  story: 接口  title: 用例标题  request:    method: get    url: https://api.weixin.qq.com/cgi-bin/token    params:      grant_type: ""      appid: wx74a8627810cfa308      secret: e40a02f9d79a8097df497e6aaf93ab80  validate: null
复制代码
运行后会实验两遍,由于test_01.yaml中有两个
测试效果部门输出如下:
  1. test_01.py::TestClass::test_01[casedata0] +++++++++++++++++++++++++casedata= {'feature': '模块', 'story': '接口', 'title': '用例标题', 'request': {'method': 'get', 'url': 'https://api.weixin.qq.com/cgi-bin/token', 'params': {'grant_type': 'client_credential', 'appid': 'wx74a8627810cfa308', 'secret': 'e40a02f9d79a8097df497e6aaf93ab80'}}, 'validate': None}
  2. 方法类型: get
  3. res的值是: {'access_token': '85_LkgiOZEurfn3XsEC1oGZCJso26U8QXM6LfVp-pNpcvMgwG-g7sZvBlU72t0XSJy-qaqggOghZRC1aIpC207qBJDG9IDrQRf_bLMoysDJzGskpGDmUCyaK80HOmcUNMeAAAMFE', 'expires_in': 7200}
  4. value的值是: 85_LkgiOZEurfn3XsEC1oGZCJso26U8QXM6LfVp-pNpcvMgwG-g7sZvBlU72t0XSJy-qaqggOghZRC1aIpC207qBJDG9IDrQRf_bLMoysDJzGskpGDmUCyaK80HOmcUNMeAAAMFE
  5. PASSED
  6. test_01.py::TestClass::test_01[casedata1] +++++++++++++++++++++++++casedata= {'feature': '模块', 'story': '接口', 'title': '用例标题', 'request': {'method': 'get', 'url': 'https://api.weixin.qq.com/cgi-bin/token', 'params': {'grant_type': '', 'appid': 'wx74a8627810cfa308', 'secret': 'e40a02f9d79a8097df497e6aaf93ab80'}}, 'validate': None}
  7. 方法类型: get
  8. res的值是: {'errcode': 40002, 'errmsg': 'invalid grant_type rid: 670a6663-665fbd17-67182a03'}
  9. FAILED
复制代码
可以看到test_01方法实验了两遍

将test_01.py代码改写为如下代码
test_tag.yaml
  1. -
  2.   feature: 模块
  3.   story: 接口
  4.   title: 用例标题
  5.   request:
  6.     method: get
  7.     url: https://api.weixin.qq.com/cgi-bin/tags/get
  8.     params:
  9.       access_token: access_token
  10.   validate: null
复制代码
改写test_tag方法
  1. @pytest.mark.parametrize("casedata", read_tests("./test_tag.yaml"))
  2.     def test_tag(self,casedata):
  3.         method = casedata["request"]["method"]
  4.         url = casedata["request"]["url"]
  5.         datas = casedata["request"]["params"]
  6.         for key,value in datas.items():
  7.             print(key,value,datas)
  8.         datas[key] = read_yaml(key)
  9.         res = RequestUtil().all_send_request(method=method, url=url, params=datas)
  10.         print("test_tag方法:",res.json())
复制代码
改写test_fileupload方法
改写前:
  1.     def test_fileupload(self):
  2.         url="https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token="+TestClass.access_token
  3.         files = {"media": open("D:\\Users\\ygl\\Desktop\\583143f57e0538868f01de8f1a15ed4.jpg","rb")}
  4.         res = RequestUtil().all_send_request(method='post', url=url, files=files)
  5.         print("test_fileupload方法:",res.json())
复制代码
改写后:
test_fileupload.yaml
  1. -
  2.   feature: 模块
  3.   story: 接口
  4.   title: 用例标题
  5.   request:
  6.     method: post
  7.     url: https://api.weixin.qq.com/cgi-bin/media/uploadimg
  8.     params:
  9.       access_token: access_token
  10.     files:
  11.       media: "D:\\Users\\ygl\\Desktop\\583143f57e0538868f01de8f1a15ed4.jpg"
  12.   validate: null
复制代码
  1.     def test_fileupload(self,casedata):
  2.         print("++++++++++++++++++++++++++casedata1=",casedata)
  3.         method = casedata["request"]["method"]
  4.         url = casedata["request"]["url"]
  5.         datas = casedata["request"]["params"]
  6.         for key,value in datas.items():
  7.             datas[key] = read_yaml(key)
  8.         files = casedata["request"]["files"]
  9.         for key,value in files.items():
  10.             files[key] = open(value,"rb")
  11.         res = RequestUtil().all_send_request(method=method, url=url, params=datas, files=files)
  12.         print("test_fileupload方法",res.json())
复制代码
天生Allure陈诉
1.下载allure而且设置环境变量设置到path内里
2.pytest.ini中修改为addopts = -vs --alluredir=./temps --clean-alluredir
3.天生HTML的allure陈诉
将run.py修改为如下代码:
  1. import osimport timeimport pytest
  2. if __name__ == '__main__':
  3.     pytest.main()
  4.     time.sleep(3)    os.system("allure generate ./temps -o ./reports --clean")
复制代码
  1. os.system("allure generate ./temps -o ./reports --clean") 这段代码的含义是通过 Python 的 os 模块执行一个系统命令。具体来说,它的作用是使用 Allure 测试报告工具生成测试报告。
  2. 以下是各部分的详细解释:
  3. os.system(...):这是 Python 中一个用来执行系统命令的函数。它会在子shell中运行指定的命令。
  4. "allure generate ...":这是要执行的命令,调用 Allure 工具生成报告。
  5. ./temps:这是输入目录,Allure 会从这个目录读取测试结果数据。
  6. -o ./reports:这是输出目录选项,生成的报告将被保存到 ./reports 目录。
  7. --clean:这个选项表示在生成报告之前清理输出目录,也就是说如果 ./reports 目录已经存在报告文件,这个选项会删除它们,以确保生成的是最新的报告。
  8. 综上所述,这条命令的整体作用是读取 ./temps 目录中的测试结果,生成一个新的报告并将其输出到 ./reports 目录,确保输出的报告是最新的
复制代码
运行run.py控制台表现Report successfully generated to .\reports即为乐成实验

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表