如何实现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的迭代项:
- foo.txt_C
- foo.txt_D
- boo.txt_C
- boo.txt_D
- doo.txt_C
- doo.txt_D
- test_2的迭代项:
- name_foo.txt_C_D
- name_boo.txt_C_D
- name_doo.txt_C_D
- surname_foo.txt_C_D
- surname_boo.txt_C_D
- 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插件可以快速实现精细化的依赖控制:
- 安装插件
pip install pytest-dependency
- 修改测试代码
给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.'
- 原理说明
- 给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
相关产品推荐
相关产品推荐

