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

如何静态检查Python unittest测试套件中generate_scenario的调用参数?

方案:扫描unittest测试套件中generate_scenario的调用及参数校验

方法1:静态AST扫描(无需运行测试)

利用Python的抽象语法树(AST)直接解析测试代码,找出所有generate_scenario的调用并提取参数,适合快速排查常量参数的场景覆盖。

实现代码

import ast
import os
import unittest

def find_generate_scenario_calls(test_dir):
    calls = []
    for root, _, files in os.walk(test_dir):
        for file in files:
            if not file.endswith('.py'):
                continue
            file_path = os.path.join(root, file)
            with open(file_path, 'r', encoding='utf-8') as f:
                tree = ast.parse(f.read())
                for node in ast.walk(tree):
                    if isinstance(node, ast.Call) and isinstance(node.func, ast.Name) and node.func.id == 'generate_scenario':
                        # 解析位置参数
                        args = []
                        for arg in node.args:
                            args.append(arg.value if isinstance(arg, ast.Constant) else ast.dump(arg))
                        # 解析关键字参数
                        kwargs = {}
                        for kw in node.keywords:
                            kwargs[kw.arg] = kw.value.value if isinstance(kw.value, ast.Constant) else ast.dump(kw.value)
                        calls.append({
                            'file': file_path,
                            'line': node.lineno,
                            'args': args,
                            'kwargs': kwargs
                        })
    return calls

class TestScenarioCoverage(unittest.TestCase):
    def test_required_scenarios_exist(self):
        # 替换为你的测试目录路径
        test_dir = './tests'
        all_calls = find_generate_scenario_calls(test_dir)
        
        # 定义必须覆盖的场景参数组合
        required_scenarios = [
            {'args': ['user', 'normal'], 'kwargs': {'enable_log': True}},
            {'args': ['admin', 'privileged'], 'kwargs': {'enable_log': False}},
            # 按需添加更多场景
        ]
        
        # 检查缺失场景
        missing = []
        for req in required_scenarios:
            match = any(call['args'] == req['args'] and call['kwargs'] == req['kwargs'] for call in all_calls)
            if not match:
                missing.append(req)
        
        self.assertEqual(len(missing), 0, f"缺失测试场景:{missing}")

if __name__ == '__main__':
    # 直接运行可打印所有调用详情
    calls = find_generate_scenario_calls('./tests')
    for call in calls:
        print(f"文件:{call['file']} | 行号:{call['line']}")
        print(f"参数:args={call['args']}, kwargs={call['kwargs']}\n")
    # 执行测试校验
    unittest.main()

方法2:运行时捕获(适配动态参数)

如果generate_scenario的参数是动态生成的(比如变量、表达式),静态扫描无法获取实际值,可通过mock在测试运行时捕获真实参数。

实现代码

import unittest
from unittest.mock import patch
from your_project_module import generate_scenario  # 导入目标函数

captured_calls = []

def capture_call(*args, **kwargs):
    captured_calls.append({'args': args, 'kwargs': kwargs})
    return generate_scenario(*args, **kwargs)

class TestScenarioCoverage(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        # 替换原函数为带捕获逻辑的包装函数
        cls.patcher = patch('your_project_module.generate_scenario', side_effect=capture_call)
        cls.patcher.start()
    
    @classmethod
    def tearDownClass(cls):
        cls.patcher.stop()
    
    def test_scenario_coverage(self):
        # 运行所有测试用例
        suite = unittest.TestLoader().discover('./tests')
        unittest.TextTestRunner(verbosity=0).run(suite)
        
        # 校验必须覆盖的场景
        required_scenarios = [
            (('user', 'normal'), {'enable_log': True}),
            (('admin', 'privileged'), {'enable_log': False}),
        ]
        
        missing = []
        for req_args, req_kwargs in required_scenarios:
            match = any(call['args'] == req_args and call['kwargs'] == req_kwargs for call in captured_calls)
            if not match:
                missing.append((req_args, req_kwargs))
        
        self.assertEqual(len(missing), 0, f"未覆盖的场景:{missing}")

if __name__ == '__main__':
    unittest.main()

关键提示

  • 静态扫描速度快,但仅能识别常量参数;动态捕获能获取真实运行参数,但需要执行全部测试,耗时更长。
  • 如果函数被重命名(比如from module import generate_scenario as gen_scen),需调整AST扫描的函数名或mock的路径。
  • 可扩展参数匹配逻辑,比如支持部分参数匹配、正则匹配等复杂校验规则。

内容的提问来源于stack exchange,提问作者Vito De Tullio

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 09:27:14