如何用Pytest实现仅针对编译时参数编译的嵌套参数化测试
问题:Pytest实现编译时参数仅编译一次、运行时参数多测的需求
我用Python编译Verilog系统代码并做输入测试,系统包含编译时参数和运行时参数。当前用Pytest参数化的写法如下:
@pytest.mark.parametrize("C1", [3,2]) # 编译时参数 @pytest.mark.parametrize("C2", [8,1]) # 编译时参数 @pytest.mark.parametrize("R1", [8,3]) # 运行时参数 @pytest.mark.parametrize("R2", [8,2]) # 运行时参数 def test_design(C1,C2,R1,R2): compile(C1,C2) prepare_inputs(C1,C2,R1,R2) run(C1,C2,R1,R2) compare_results(C1,C2,R1,R2)
这种写法会执行16次测试,且重复编译16次。我希望仅针对每组编译时参数(共4组)编译一次,再针对每组运行时参数执行测试,逻辑如下:
for C1 in [3,2]: for C2 in [8,1]: compile(C1,C2) for R1 in [8,3]: for R2 in [8,2]: prepare_inputs(C1,C2,R1,R2) run(C1,C2,R1,R2) compare_results(C1,C2,R1,R2)
请问如何用Pytest实现该需求?(已参考相关嵌套参数化测试内容,但仍未理解如何仅针对部分参数执行编译操作)
解决方案
核心思路是用参数化的Fixture处理编译时参数,借助Fixture的缓存机制,确保每组编译参数只执行一次编译。以下是两种可行实现方式:
方法1:参数化Fixture + 运行时参数单独参数化
定义参数化的Fixture来封装编译逻辑,设置合适的作用域缓存编译结果;再在测试函数中单独参数化运行时参数。
import pytest # 编译参数的参数化Fixture,scope设为module确保每组C1/C2只编译一次 @pytest.fixture(scope="module", params=[(3,8), (3,1), (2,8), (2,1)]) def compiled_design(request): C1, C2 = request.param # 执行编译操作,可返回编译产物或参数供后续测试使用 compile(C1, C2) yield C1, C2 # 可选:测试完成后清理编译生成的文件/资源 # cleanup_compiled_files(C1, C2) # 对运行时参数进行参数化 @pytest.mark.parametrize("R1", [8,3]) @pytest.mark.parametrize("R2", [8,2]) def test_design(compiled_design, R1, R2): C1, C2 = compiled_design prepare_inputs(C1, C2, R1, R2) run(C1, C2, R1, R2) compare_results(C1, C2, R1, R2)
方法2:类级参数化 + 类作用域Fixture
用测试类组织编译参数,搭配类作用域的Fixture执行单次编译,再在类方法中参数化运行时参数。
import pytest # 类级参数化编译参数组合 @pytest.mark.parametrize("C1,C2", [(3,8), (3,1), (2,8), (2,1)]) class TestVerilogDesign: # 类作用域Fixture,每个类实例(对应一组C1/C2)执行一次编译 @pytest.fixture(scope="class", autouse=True) def compile_design(self, C1, C2): compile(C1, C2) yield # 可选:清理编译资源 # cleanup_compiled_files(C1, C2) # 运行时参数的参数化测试方法 @pytest.mark.parametrize("R1", [8,3]) @pytest.mark.parametrize("R2", [8,2]) def test_run(self, C1, C2, R1, R2): prepare_inputs(C1, C2, R1, R2) run(C1, C2, R1, R2) compare_results(C1, C2, R1, R2)
关键说明
- Fixture作用域:
scope="module"或scope="class"确保每组编译参数对应的编译操作只执行一次,避免重复编译。 - 参数化逻辑拆分:将编译参数和运行时参数的参数化分离,编译参数由Fixture处理,运行时参数在测试函数/方法上单独参数化,总测试次数仍为16次,但编译仅执行4次。
内容的提问来源于stack exchange,提问作者Abarajithan
相关产品推荐
相关产品推荐

