如何在pytest-bdd的When步骤中使用pytest.raises?
处理BDD异常场景的方案
针对你提出的需求——在执行When I perform an operation步骤前启动pytest.raises上下文,同时不污染该步骤的其他正常用法,这里有几个可行的方案:
方案1:扩展带标识的When步骤
给异常场景单独定义一个带明确标识的When步骤,内部复用原步骤逻辑并包裹异常捕获,完全不影响原步骤:
修改Gherkin场景
Scenario: An erroneous operation Given some data And some more data When I perform an operation that should fail Then an exception is raised
步骤定义
from pytest_bdd import when, then import pytest # 原正常步骤保持不变 @when("I perform an operation") def perform_normal_operation(): do_the_actual_operation() # 异常场景专用步骤,包裹原逻辑 @when("I perform an operation that should fail") def perform_failing_operation(): with pytest.raises(Exception): # 替换为你期望的具体异常类型 perform_normal_operation() @then("an exception is raised") def verify_exception(): # pytest.raises已完成捕获验证,此处可留空或做额外检查 pass
方案2:用上下文开关fixture
通过一个可配置的fixture作为开关,在异常场景的Given步骤中开启捕获,When步骤根据开关状态决定是否启用pytest.raises:
定义开关fixture
import pytest @pytest.fixture(scope="function") def exception_catcher(): class Catcher: def __init__(self): self.enabled = False self.exc_type = None def enable(self, exc_type): self.enabled = True self.exc_type = exc_type return Catcher()
步骤定义
from pytest_bdd import given, when, then import pytest import importlib # 新增Given步骤用于开启异常捕获 @given("I expect an exception of type <exc_class_name>") def enable_exception_catcher(exception_catcher, exc_class_name): # 动态导入异常类,支持传入如"ValueError"这类名称 mod = importlib.import_module("builtins") exc_class = getattr(mod, exc_class_name) exception_catcher.enable(exc_class) # 原When步骤添加开关判断 @when("I perform an operation") def perform_operation(exception_catcher): if exception_catcher.enabled: with pytest.raises(exception_catcher.exc_type): do_the_actual_operation() else: do_the_actual_operation() @then("an exception is raised") def verify_exception(): pass
对应Gherkin场景
Scenario: An erroneous operation Given some data And some more data And I expect an exception of type "ValueError" When I perform an operation Then an exception is raised
方案3:基于场景标签的钩子处理
给异常场景添加专属标签,通过pytest-bdd钩子检测标签,在When步骤中自动启用异常捕获:
带标签的Gherkin场景
@expected_exception(ValueError) Scenario: An erroneous operation Given some data And some more data When I perform an operation Then an exception is raised
钩子与步骤定义
import pytest from pytest_bdd import when, then import importlib # 钩子函数解析场景标签,标记是否需要捕获异常 def pytest_bdd_before_scenario(request, scenario): for tag in scenario.tags: if tag.startswith("expected_exception("): exc_class_name = tag.split("(")[1].rstrip(")") mod = importlib.import_module("builtins") request.node.exc_type = getattr(mod, exc_class_name) break # When步骤根据钩子标记处理 @when("I perform an operation") def perform_operation(request): if hasattr(request.node, "exc_type"): with pytest.raises(request.node.exc_type): do_the_actual_operation() else: do_the_actual_operation() @then("an exception is raised") def verify_exception(): pass
所有方案的核心思路都是隔离异常场景与正常场景的逻辑,避免修改原步骤的全局行为,确保原步骤在其他场景中仍能正常使用。
内容的提问来源于stack exchange,提问作者asthasr
相关产品推荐
相关产品推荐

