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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 10:01:19