详解pytest中 conftest.py 的作用

发布于:2025-05-12 ⋅ 阅读:(14) ⋅ 点赞:(0)

conftest.py 是 pytest 框架中用于共享测试配置的核心文件,支持层级化管理和自动发现机制。以下是其核心作用及用法详解:

1. 共享 Fixture

  • 作用:定义公共测试夹具(Fixture),供多个测试模块复用,避免重复代码。

  • 示例

    # conftest.py
    import pytest
    
    @pytest.fixture(scope="session")
    def database_connection():
        conn = create_db_connection()
        yield conn
        conn.close()
  • 使用范围

    • 同级目录及所有子目录的测试文件均可使用该 Fixture。

    • 不同层级的 conftest.py 中 Fixture 按就近原则覆盖。

  • 作用域

  1. function默认作用域
  2. class
  3. module
  4. package
  5. session
  • ​​​​setup 函数和​​​​teardown函数

如果想在测试用例或者测试类执行前后都加上重复执行的代码,例如:

使用​​​​setup 函数完成初始化测试环境​​:在测试用例执行前完成准备工作,例如创建数据库连接、生成测试数据、启动浏览器等;

使用​​​​teardown函数完成​​清理测试环境​​:在测试用例执行后释放资源,例如关闭数据库连接、删除临时文件、释放内存

pytest 支持多层级作用域,不同层级的 setup/teardown 按以下顺序执行:
​​会话级(Session)​​
通过 setup_session/teardown_session 实现,整个测试会话(所有模块)执行一次。
​​适用场景​​:全局资源初始化(如启动服务集群)。
​​模块级(Module)​​
使用 setup_module/teardown_module,单个 .py 文件执行前后各运行一次。
​​示例​​:加载测试数据。
​​类级(Class)​​
通过 setup_class/teardown_class 实现,每个测试类执行一次。
​​适用场景​​:初始化类内共享资源(如日志对象、API 请求客户端)。
​​方法级(Method)​​
使用 setup_method/teardown_method,每个测试方法(类中的函数)执行前后运行。
​​示例​​每个用例创建独立浏览器实例。
​​函数级(Function)​​
通过 setup_function/teardown_function 实现,适用于类外的独立测试函数。
​​适用场景​​:函数级数据准备(如参数化测试输入)

代码demo如下:

class TestCase():
    def setup_class(self):
        print("====整个测试类开始前只执行一次setup_class====")

    def teardown_class(self):
        print("====整个测试类结束后只执行一次teardown_class====")

    def setup_method(self):
        print("==类里面每个用例执行前都会执行setup_method==")

    def teardown_method(self):
        print("==类里面每个用例结束后都会执行teardown_method==")

    def test_1(self):
        print("测试功能点1")


    def test_2(self):
        print("测试功能点2")


if __name__ == '__main__':
    pytest.main(["-q", "-s"])

输出

============================= test session starts =============================
collecting ... collected 2 items

test_fixture1.py::TestCase::test_1 ====整个测试类开始前只执行一次setup_class====
==类里面每个用例执行前都会执行setup_method==
PASSED                                [ 50%]测试功能点1
==类里面每个用例结束后都会执行teardown_method==

test_fixture1.py::TestCase::test_2 ==类里面每个用例执行前都会执行setup_method==
PASSED                                [100%]测试功能点2
==类里面每个用例结束后都会执行teardown_method==
====整个测试类结束后只执行一次teardown_class====


============================== 2 passed in 0.03s ==============================
 

使用conftest.py实现setup 函数和​​​​teardown函数的功能

在conftest.py编写代码如下:

import pytest


@pytest.fixture(scope="function")
def fixture_method():
    print("==类里面每个用例执行前都会执行setup_method==")
    yield
    print("==类里面每个用例结束后都会执行teardown_method==")


@pytest.fixture(scope="class")
def fixture_class():
    print("====整个测试类开始前只执行一次setup_class====")
    yield
    print("====整个测试类结束后只执行一次teardown_class====")

测试用例py文件代码如下:

import pytest

class TestCase():
 def test_1(self,fixture_method,fixture_class):
    print("测试功能点1")


 def test_2(self,fixture_method,fixture_class):
    print("测试功能点2")


if __name__ == '__main__':
    pytest.main(["-q", "-s"])

很显然测试用例中的代码看起来,清爽了很多很多,执行代码会有同样的效果

2. 层级化配置

  • 目录结构示例

    project/
    ├── conftest.py          # 作用范围:全局
    └── tests/
        ├── conftest.py      # 作用范围:tests 目录
        └── subdir/
            ├── conftest.py  # 作用范围:subdir 目录
            └── test_b.py
  • 优先级:子目录的 conftest.py 优先级高于父目录,同名 Fixture 会被覆盖。

3. 钩子函数(Hooks)

  • 自定义 pytest 行为:Pytest 提供了丰富的钩子函数(Hook),允许在测试生命周期不同阶段进行自定义扩展。

关于钩子函数,大家可以参考文章:

4. 自动发现机制

  • 文件名固定:必须命名为 conftest.py,否则 pytest 无法识别。

  • 无需导入:Fixture 和钩子函数会被 pytest 自动发现,测试文件直接通过名称引用。

5. 其他用途

  • 插件加载:在 conftest.py 中初始化插件或外部库。

  • 全局配置:设置全局变量、环境变量或模拟外部服务。

示例场景

假设需要为 API 测试提供鉴权 Token:

# conftest.py
import pytest

@pytest.fixture(scope="module")
def auth_token():
    token = get_token_from_api()
    return token

测试文件直接使用:

# test_api.py
def test_user_profile(auth_token):
    headers = {"Authorization": f"Bearer {auth_token}"}
    response = call_api(headers)
    assert response.status_code == 200

总结

  • 核心价值:通过 conftest.py 实现测试配置的模块化、复用和层级管理。

  • 适用场景:共享 Fixture、自定义钩子、环境配置、插件集成等。

  • 最佳实践:将通用配置放在高层级 conftest.py,局部配置放在子目录中。


网站公告

今日签到

点亮在社区的每一天
去签到