pytest中使用conftest做测试前置和参数化

pytest中比较高阶的应用是,使用conftest去做测试前置工作、测试收尾工作和参数化。conftest是pytest的一个组件,用于配置测试环境和参数。通过conftest, 可以创建一个可复用的测试配置文件,以便在多个测试模块之间共享配置信息。即,conftest主要用来存放fixture,管理一些全局的fixture.

适用场景:

  • 多个测试用例文件(test_*.py)的所有用例都需要用登录功能作为前置操作,那就不能把登录功能写到某个用例文件中去了,这个时候就可以把登录功能写成一个fixture,放到conftest.py里
  • 多个case共享一套测试数据
  • 多个case共享配置信息

conftest.py配置fixture注意事项

  • pytest会默认读取conftest.py里面所有的fixture
  • conftest.py文件名称是固定的,不能改动
  • conftest.py只对同一个package下的所有测试用例生效
  • 不同目录可以有自己的conftest.py, 一个项目可以有多个conftest.py
  • 测试用例文件中不需要手动import conftest.py, pytest会自动查找
  • 在conftest.py文件中,可以定义函数、类和变量,以供测试用例中使用。这些配置可以通过参数传递给测试用例。配合测试用例中的pytest.mark.parametrize装饰器来传递参数。
  • conftest.py如果在项目根目录下,那就是对整个项目下的测试用例生效

conftest结合fixture使用

  • scope参数为session: 所有测试.py文件执行前执行一次
  • scope参数为module: 每一个测试.py文件执行前都会执行一次conftest文件中的fixture
  • scope参数为class: 每一个测试文件中的测试类执行前都会执行一次conftest文件中的fixture
  • scope参数为function:所有文件的测试用例执行前都会执行一次conftest文件中的fixture,默认scope为function.

例子:

python 复制代码
conftest.py

data = excel_util.get_cell_range_data(CASE_BASE_PATH, CASE_INFO_SHEET, 2, 2, 1, 10)


@pytest.fixture(params=data)  # 这里使用了参数化
def login(request):   # 登录功能,返回uuid, token
    param = request.param
    url = param['url']
    api = param['api']
    params = param['parameter']
    params = substitution_tool.var_substitute(params, '登录')
    globalVar = param['globalVar']  
    url += api + '&' + params
    res = request_util.send_httprequest('post', url).json()  
    print("res=", res)
    
    gv = globalVar_util.saveGlobals(res, globalVar)  #这里把uuid,token保存到全局变量中
    yield gv # 返回包含有uuid,token的字典gv

这是一个封装登录功能的fixture, 通过params=data先传入登录需要的用户名和密码数据,然后经过fixture实现返回uuid,token的功能。

python 复制代码
conftest.py

@pytest.fixture()
def case_info(request):   # 获取测试用例的数据
    param = request.param
    return param

这是一个结合pytest.mark.parametrize装饰器实现参数传递的fixture, 可以读取excel表格中的测试用例信息。

看测试文件中的测试方法:

python 复制代码
data_login_state = excel_util.get_cell_range_data(CASE_BASE_PATH, CASE_INFO_SHEET, 3, 6, 1, 9)


@allure.severity("normal")
@pytest.mark.parametrize("case_info", data_login_state, indirect=True)
def test_login_tai(case_info, login):
    caseId = case_info['caseId']
    apiName = case_info['apiName']
    caseTitle = case_info['caseTitle']
    params = case_info['parameter']
    '''
    for key in login.keys():
        value = login.get(key)
        if key in params:
            params = params.replace('${'+key+'}', str(value))
    '''
    params = substitution_tool.gv_substitute(params)
    url = case_info['url']
    api = case_info['api']
    url += api + '&' + params
    print("url=", url)
    print(f"caseId: {caseId}, apiName:{apiName}, caseTitle:{caseTitle} begins to test!")
    logger.info(f"caseId: {caseId}, apiName:{apiName}, caseTitle:{caseTitle} starts to test!")
    assertFields = case_info['assertFields']
    res = request_util.send_httprequest('post', url).json()
    assert_util.assert_result(res, assertFields)

这里就结合pytest.mark.parametrize装饰器实现参数的传递,这里方法test_login_tai使用了两个fixture,一个是login, 一个是case_info, 两个fixture一块使用,既接收到了login返回的uuid,token, 又实现了测试用例的参数化。其中,indirect=True代表case_info是作为函数传递给test_login_tai方法的,不是作为变量。

最后使用pytest命令去执行pytest --html=./testreport.html

测试执行情况如上,日志信息有caseId, apiName, caseTitle.

生成的testreport.html测试报告:

相关推荐
Madison-No72 天前
pytest框架
pytest
凛铄linshuo7 天前
分析业务流程什么时候适合断言?
python·pytest
凛铄linshuo8 天前
自动化测试:pytest第一个实例学习
学习·pytest
Helix25011 天前
Python单元测试实战:pytest框架从入门到企业级测试体系搭建指南
python·单元测试·实战·mock·pytest·测试覆盖率·fixture
在世修行15 天前
干货:pytest
pytest·fixture·pytest assert
小小龙学IT17 天前
Python pytest 测试框架深度解析:从断言重写到插件生态的工程化测试体系
网络·python·pytest
落魄大学生之流水线上谋生计19 天前
pytest 入门与实践:从第一个测试到可维护的测试体系
pytest
念越20 天前
Allure 测试报告保姆级教程:从安装到 pytest 集成与报告生成
pytest·allure
念越21 天前
接口自动化测试从入门到实战:接口用例设计、Requests、Pytest、YAML、JSON Schema 与 Allure 报告
python·测试工具·自动化·json·pytest
霍格沃兹测试学院-小舟畅学25 天前
AI+Swagger:一键生成500条pytest接口用例
人工智能·pytest