20个Requests + Pytest高效测试技巧
1.1 Pytest优势:Pytest不仅仅是一个测试框架,它更像是一个"测试生态系统"。它的fixture机制让测试数据管理变得优雅,parametrize装饰器让批量测试成为可能。
1.2 Requests 优势:Requests库则是Python HTTP客户端的"瑞士军刀",API简洁到让人怀疑人生。
1.3 组合威力:Requests 负责“通信”, Pytest 负责“组织、运行、断言、报告”,分工明确,效率倍增。
02 Requests+Pytest基础筑基
2.1 环境准备
Python 环境确认 (推荐 Python 3.6+)
安装必备库:pip install requests pytest
2.2 Pytest 入门三板斧:
-
编写测试用例: 一个以 test_ 开头的函数就是一个测试用例!
-
断言: 使用简单的 assert 语句 (assert response.status_code == 200, assert response.json()["code"] == 0)。
-
运行测试: 在命令行执行 pytest (自动发现并运行 test_*.py 文件中的 test_* 函数)。
2.3 Requests 核心三剑客:
-
GET 请求:获取资源,处理查询参数 (params)。
-
POST 请求:提交数据,处理表单 (data) 和 JSON (json) 数据。
-
解析响应:status_code (状态码), headers (响应头), text (文本内容), json() (解析JSON响应体) - 重点演示 json() 在接口测试中的关键作用。
(可选快速提) PUT, DELETE, PATCH 等其他方法。
03Requests+Pytest进阶技巧
接口测试,即是对接口测试用例进行的一次工具测试执行过程;这中间就牵扯到两个点,一是接口测试用例的整体提效,二是对工具的提效;
3.1接口测试用例提效技巧如下:
以下是某网友分享的自己整理接口测试用例的两种方式,感觉挺好,也分享给大家:
第一种是使用excel或者yaml文件来编写测试数据,使用@pytest.mark.parametrize装饰器循环读取测试数据。

如上图,读取excel表格来进行测试用例生成;
优势:代码量少,主要维护数据。
第二种,将每一个接口封装成一个函数,直接在pytest框架内进行测试用例的编写。这种相比第一种代码量多。

优势:可以很灵活地调用,看着整洁。
封装思路如下:
将每个模块的接口分类整理在一个py文件中这样便于找到对应接口位置。
1,首先对request函数进行二次封装,可以在封装的函数内加上请求头,日志以及其他自己相加的东西,这样的好处是只要后续发起请求是调用这个二次封装的函数,只需要改封装的地方,所有的接口都会生效。
2,封装接口请求,如下示例:
class A: @staticmethod def api(**kwargs): “““ 写注释 :return: ””” url = "/a" param ={ 'a': kwargs.get('a') 'b': kwargs.get('b')
} response = sendrequest( method:'GET'url=url,params=param)
return response.json()
3.2工具提效的技巧如下:(主要整理了Pytest的提效技巧)
参数化黑科技
1. 跨文件参数化
#conftest.py defpytest_generate_tests(metafunc): if"user"inmetafunc.fixturenames: metafunc.parametrize("user",["admin","guest"],indirect=True)
2. JSON动态参数
importjson importpytest withopen("test_data.json")asf: TEST_DATA=json.load(f) @pytest.mark.parametrize("case",TEST_DATA,ids=lambdax:x["case_name"]) deftest_api(case): assertcase["input"]*2==case["expect"]
3. 条件参数化
@pytest.mark.parametrize( "env", ["prod"]ifos.getenv("CI")else["dev","staging"] )
4. 参数化+夹具组合技
@pytest.fixture deflogin_user(request): returnf"user_{request.param}" @pytest.mark.parametrize("login_user",[1,2],indirect=True) deftest_order(login_user): print(f"测试用户:{login_user}")#输出user_1/user_2
5. 参数化跳过
@pytest.mark.parametrize("mode",[ pytest.param("slow",marks=pytest.mark.skip(reason="太慢")), "fast" ])
测试标记
6. 标记自动跳过
@pytest.mark.skipif( sys.platform=="win32", reason="Windows平台不测试此功能" )
7. 标记依赖
@pytest.mark.dependency() deftest_login(): pass @pytest.mark.dependency(depends=["test_login"]) deftest_pay(): pass
8. 自定义标记分类
#pytest.ini [pytest] markers= smoke:冒烟测试 performance:性能测试
9. 标记排序
@pytest.mark.run(order=2)
deftest_step2():
assert1+1==2
10. 标记超时
@pytest.mark.timeout(10)#10秒超时 deftest_slow_api(): time.sleep(15)#将触发TimeoutExpired
夹具魔法
11. 自动清理夹具
@pytest.fixture deftemp_db(tmp_path): db_path=tmp_path/"test.db" yieldDatabase(db_path) db_path.unlink()#测试后自动删除
12. 作用域控制
@pytest.fixture(scope="module")#整个模块只执行一次 defredis_conn(): returnRedis(host="test-redis")
13. 夹具参数化
@pytest.fixture(params=[0,1,2])
defthree_users(request):
returnUser(id=request.param)
14. 夹具重试
@pytest.fixture(retry=3)#失败自动重试 defflaky_api(): returnget_unstable_api()
15. 动态夹具
defpytest_generate_tests(metafunc): if"dynamic_fixture"inmetafunc.fixturenames: metafunc.fixturenames.append("extra_data")#运行时动态添加夹具
插件实战
16. 性能分析
@pytest.mark.profile deftest_performance(): #用cProfile分析性能
17. 失败重跑
pytest--reruns3--reruns-delay1#失败后重试3次,间隔1秒
18. 并行测试加速
pytest-nauto#自动使用所有CPU核心
19. 测试覆盖率
pytest--cov=src--cov-report=html
20. 自定义报告
#conftest.py defpytest_terminal_summary(terminalreporter): terminalreporter.write_line("??本次测试关键指标:") terminalreporter.write_line(f"通过率:{passed/total*100}%")

浙公网安备 33010602011771号