一、使用fixture实现部分前后置

与传统的 setup/teardown 方法相比,fixture 更灵活,可以选择性地应用于特定测试,实现部分测试用例的前后置处理

1.基本概念

  • 作用:在测试函数执行前后执行特定代码,提供测试依赖的资源(如数据库连接、临时文件等)。
  • 定义方式:使用 @pytest.fixture 装饰器定义函数。
  • 语法:@pytest.fixture(scope="作用域",params="数据驱动",autouser="自动执行",ids="自定义参数名称",name="别名")。
  • 执行时机:默认每个测试函数调用一次(scope="function")。

scope="作用域"

functioin(默认):在每个方法(测试用例)的前后执行一次。

class:在每个类的前后执行一次。

module:在每个py文件前后执行一次。

package/session:每个package前后执行一次。

function级别:在每个函数的前后执行

  1. scope="function" 配置在每个函数的前后执行
  2. execute_sql作为参数传递给 test_query,该测试会执行前后置逻辑。
  3. 通过 yield 返回连接对象yield conn将数据库连接信息传递给使用这个 fixture 的测试函数
import pytest
class Test_Fixture: 
    @pytest.fixture(scope="function")
    def execute_sql(self):
        print("\n[前置操作],连接数据库")
        conn = {"status":"connected"}
        yield conn
        print("\n[后置操作],关闭数据库连接")
    
    # 仅需要数据库连接的测试函数传入fixture名称
    def test_query(self,execute_sql):
        assert execute_sql["status"] == "connected"
        print("执行数据库的查询...")
        
    # 不需要数据库连接的测试函数不传入fixture
    def test_calculation(self):
        assert 1+1 == 2

image-20250705105350947

注意:如果加入autouse=True参数,那么表示自动使用,那么和setup、teardown功能一致。

class级别:在每个类的前后执行一次。

scope="class":指定 fixture 的作用域为类级别,表示每个测试类只执行一次这个 fixture

@pytest.mark.usefixtures("execute_sql"):这是 pytest 的标记,用于将execute_sqlfixture 应用到整个测试类

def test_query(self, execute_sql):测试方法显式接收execute_sql参数,这样可以在测试中使用 fixture 返回的conn对象

import pytest

@pytest.fixture(scope="class")
def execute_sql():
    print("\n[前置操作],连接数据库")
    conn = {"status":"connected"}
    yield conn
    print("\n[后置操作],关闭数据库连接")

@pytest.mark.usefixtures("execute_sql")
class Test_Fixture_Class: 
    def test_query(self,execute_sql):
        assert execute_sql["status"] == "connected"
        print("执行数据库的查询...")
        
#不需要数据库连接的测试函数放入类外
def test_calculation():
    assert 1+1 == 2

image-20250705114600884

module级别:在每个模块的前后执行一次,和setup_module和teardown_module效果一样

import pytest
@pytest.fixture(scope="module",autouse=True)
def execute_sql():
    print("\n[前置操作],连接数据库")
    conn = {"status":"connected"}
    yield conn
    print("\n[后置操作],关闭数据库连接")


def test_query(execute_sql):
    assert execute_sql["status"] == "connected"
    print("执行数据库查询操作...")

参数化fixture

通过 params 参数,fixture 可以提供多组数据,使测试函数自动运行多次。

import pytest

@pytest.fixture(params=["chrome","firefox","safari"])
def browser(request):
    print(f"\n[前置操作] 启动 {request.param}")
    yield request.param
    print(f"[后置操作] 关闭 {request.param}")
    
def test_ui(browser):
    print(f"在{browser} 上测试UI元素...")

image-20250705181748247

二、package/session 级别 fixture 与 conftest.py 的配合

1. 为什么 package/session 级别 fixture 需要 conftest.py

  • package 级别 fixture:在整个包(一个包含 __init__.py 的文件夹)的所有测试执行前初始化一次,包内所有测试共享该资源,测试结束后执行清理操作。
  • session 级别 fixture:在整个测试会话(所有测试开始到结束)中只初始化一次,所有测试模块、包共享该资源,会话结束后清理。

2. conftest.py 的核心作用

  • 自动识别:pytest 会自动扫描项目中的 conftest.py 文件,其中定义的 fixture 无需通过 import 即可被同级或子级模块的测试函数使用。

  • 作用域隔离:不同目录的 conftest.py 只对当前目录及子目录的测试生效,避免全局污染。

3. 实战示例:package/session 级别 fixture + conftest.py

步骤 1:在 conftest.py 中定义 package/session 级别 fixture

import pytest

@pytest.fixture(scope="session")
def global_config():
    print("\n[session前置] 加载全局配置(仅一次)")
    config = {"env" : "test", "timeout":30}
    yield config
    print("\n[session后置] 清理全局资源")
    
@pytest.fixture(scope="package")
def package_logger():
    print("\n[package前置] 初始化包日志")
    logger = {"name" : "package_logger"}
    yield logger
    print("\n[package后置] 关闭包日志")

步骤 2:在测试模块中使用共享 fixture

无需导入 conftest.py,直接在测试函数中通过参数引用 fixture 即可。

# test_package1/test_module1.py
def test_case1(global_config, package_logger):
    print(f"使用全局配置:{global_config}")
    print(f"使用包日志:{package_logger}")
    assert global_config["env"] == "test"

# test_package2/test_module2.py
def test_case2(global_config, package_logger):
    print(f"跨包使用全局配置:{global_config}")
    print(f"当前包日志:{package_logger}")
    assert package_logger["name"] == "package_logger"

执行结果与解析

image-20250706132143520

4. 关键注意事项

conftest.py 位置

  • fixture 作用域为 sessionconftest.py 需放在项目根目录,确保所有测试能识别。

  • fixture 作用域为 packageconftest.py 需放在对应包的目录下,仅对该包生效。

三、allure 报告生成(Mac系统上)

  1. 从github上下载allure的zip形式的压缩包
https://github.com/allure-framework/allure2/releases
  1. 解压zip包,并且获取到bin的路径:

博主解压出来的的allure路径是:

/private/var/www/html/allure-2.34.1/bin
  1. 配置allure的环境变量
  • 在终端输入
vim ~/.bash_profile
  • 添加allure的路径
export PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin
export PATH=${PATH}:自己本地allure的bin目录的路径
  • 保存文件,接着输入以下命令使环境变量生效
source ~/.bash_profile
  1. 验证是否生效

pytest.ini文件加入以下命令,指定 Allure 报告的原始数据

addopts = -vs --alluredir=reports/temps --clean-alluredir

image-20250706135035687

启动 Allure 测试报告服务器,它会读取 ./reports/temps 目录下的测试结果数据,并在本地启动一个临时的 Web 服务器来展示这些数据。

os.system("allure serve ./reports/temps")

image-20250706135816300

运行后会自动在浏览器中打开报告页面。

image-20250706140042011