You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现Pytest中test_2迭代与test_1迭代的关联依赖?

问题场景

以下是两个pytest测试函数:

from pathlib import Path
import pandas as pd
import pytest

@pytest.mark.parametrize('feed', ['C', 'D'])
@pytest.mark.parametrize('file', ['foo.txt', 'boo.txt', 'doo.txt'])
def test_1(feed: Path, file: str):
    assert (Path(feed / file).is_file()), 'Not file'


@pytest.mark.parametrize('feed_C, feed_D', [('C', 'D')])
@pytest.mark.parametrize('file', ['foo.txt', 'boo.txt', 'doo.txt'])
@pytest.mark.parametrize('column', ['name', 'surname'])
def test_2(feed_C: Path, feed_D: Path, file: str, column: str):
    df1 = pd.read_csv(Path(feed_C / file), sep="\t")
    df2 = pd.read_csv(Path(feed_D / file), sep="\t")
    
    assert df1[column].equals(df2[column]), 'data frames are not equal.'

测试用例迭代结构

  • test_1的迭代项:
    1. foo.txt_C
    2. foo.txt_D
    3. boo.txt_C
    4. boo.txt_D
    5. doo.txt_C
    6. doo.txt_D
  • test_2的迭代项:
    1. name_foo.txt_C_D
    2. name_boo.txt_C_D
    3. name_doo.txt_C_D
    4. surname_foo.txt_C_D
    5. surname_boo.txt_C_D
    6. surname_doo.txt_C_D

需求

test_2中每个与某文件绑定的迭代(比如name_foo.txt_C_D、surname_foo.txt_C_D),需要依赖test_1中该文件对应的两个feed测试结果(即foo.txt_C和foo.txt_D)。只要这两个test_1用例中有一个未通过,就跳过test_2中该文件的所有迭代项。


解决方案

方案一:使用pytest-dependency插件(推荐)

借助pytest-dependency插件可以快速实现精细化的依赖控制:

  1. 安装插件
pip install pytest-dependency
  1. 修改测试代码
    给test_1的每个用例设置唯一依赖标记,test_2针对每个文件绑定对应的两个test_1用例:
from pathlib import Path
import pandas as pd
import pytest

@pytest.mark.parametrize('feed', ['C', 'D'])
@pytest.mark.parametrize('file', ['foo.txt', 'boo.txt', 'doo.txt'])
@pytest.mark.dependency(name="test1_{file}_{feed}")
def test_1(feed: str, file: str):
    assert (Path(feed) / file).is_file(), 'Not file'


@pytest.mark.parametrize('feed_C, feed_D', [('C', 'D')])
@pytest.mark.parametrize('file', ['foo.txt', 'boo.txt', 'doo.txt'])
@pytest.mark.parametrize('column', ['name', 'surname'])
@pytest.mark.dependency(depends=["test1_{file}_C", "test1_{file}_D"])
def test_2(feed_C: str, feed_D: str, file: str, column: str):
    df1 = pd.read_csv(Path(feed_C) / file, sep="\t")
    df2 = pd.read_csv(Path(feed_D) / file, sep="\t")
    
    assert df1[column].equals(df2[column]), 'data frames are not equal.'
  1. 原理说明
  • 给test_1的每个用例通过name参数设置唯一标识,确保每个文件+feed组合都有独立标记。
  • test_2通过depends参数绑定当前文件对应的两个test_1用例,只要其中一个失败,该文件下的所有test_2迭代都会被自动跳过。

方案二:不依赖第三方插件(手动缓存)

如果不想使用插件,可以利用pytest的缓存机制手动实现:

from pathlib import Path
import pandas as pd
import pytest

@pytest.mark.parametrize('feed', ['C', 'D'])
@pytest.mark.parametrize('file', ['foo.txt', 'boo.txt', 'doo.txt'])
def test_1(feed: str, file: str, request):
    result = (Path(feed) / file).is_file()
    assert result, 'Not file'
    # 将测试结果存入缓存
    request.config.cache.set(f"test1_{file}_{feed}", result)


@pytest.mark.parametrize('feed_C, feed_D', [('C', 'D')])
@pytest.mark.parametrize('file', ['foo.txt', 'boo.txt', 'doo.txt'])
@pytest.mark.parametrize('column', ['name', 'surname'])
def test_2(feed_C: str, feed_D: str, file: str, column: str, request):
    # 读取缓存中对应文件的两个feed测试结果
    pass_c = request.config.cache.get(f"test1_{file}_C", None)
    pass_d = request.config.cache.get(f"test1_{file}_D", None)
    
    # 任一用例未通过/未执行则跳过当前文件的所有测试
    if pass_c is None or pass_d is None or not (pass_c and pass_d):
        pytest.skip(f"跳过文件{file}的测试:test_1中对应feed用例未通过或未执行")
    
    df1 = pd.read_csv(Path(feed_C) / file, sep="\t")
    df2 = pd.read_csv(Path(feed_D) / file, sep="\t")
    
    assert df1[column].equals(df2[column]), 'data frames are not equal.'

这个方案通过手动读写缓存来判断依赖结果,不需要额外插件,但需要自行处理跳过逻辑。


内容的提问来源于stack exchange,提问作者Rustam Karimov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 20:45:13