Python 在未加载的功能级别上表现夹具

Python behave fixture on feature level not loaded

这与 this question 有点相关,但我在下面的这个最小示例中还有一些其他问题。

为了功能测试,我准备了一个固定装置,它备份了一个文件,该文件将在测试期间进行修改运行(例如,附加了一行)。经过测试运行这个fixture恢复了原文件

项目文件:

└───features
    │   environment.py
    │   modify_file.feature
    │
    └───steps
            file_ops.py
#!/usr/bin/env python
# FILE: features/environment.py

import logging
from behave import fixture
from behave.runner import Context

logger = logging.getLogger(__name__)


@fixture
def backup_file(context: Context):
    """
    A file will be modified during the feature test.
    This fixture shall backup the file before the feature test
    and restore the backup after the test.
    """
    file = Path.home() / "important.txt"
    backup_suffix = ".backup"
    file.touch()
    file.replace(file.with_suffix(backup_suffix))
    logger.info("File backed up")
    yield
    file.with_suffix(backup_suffix).replace(file)
    logger.info("File restored")
# FILE: features/modify_file.feature

@fixture.backup.file
Feature: Modify file

        @wip
        Scenario: Append a line to a file
                Given the file exists
                When I append a line to the file
                Then the line appears at the end of the file
#!/usr/bin/env python
# File features/steps/file_ops.py

from pathlib import Path
from behave import given
from behave import when
from behave import then
from behave.runner import Context
import logging

logger = logging.getLogger(__name__)
file = Path.home() / "important.txt"


@given("the file exists")
def step_impl(context: Context):
    logger.info(f"Touching file")
    file.touch()


@when("I append a line to the file")
def step_impl(context: Context):
    logger.info(f"Appending a line to file")
    context.appended = "Test line appended\n"
    with open(file, mode="a") as f:
        f.write(context.appended)


@then("the line appears at the end of the file")
def step_impl(context: Context):
    logger.info(f"Checking if line was appended")
    with open(file, mode="r") as f:
        for line in f:
            pass
        logger.info(f"Last line is '{line.strip()}'")
        assert line == context.appended

我想在所有场景运行之前在功能级别应用fixture。待所有场景运行后恢复文件。然而,事实显然并非如此。

当我 运行 behave -w(无日志捕获,仅 wip 标签)时,我没有看到正在输出的夹具的任何日志行以及每个 运行 我看到文件中附加了另一行。这意味着文件没有被备份和恢复。即使在我将夹具向下移动到场景级别 modify_file.feature 文件中,也不会应用夹具。

你能帮我理解这是怎么回事吗?我也很好奇为什么夹具标签使用点符号 (@fixture.backup.file) 而不是 (fixture.backup_file),因为这与实际函数名称相似。 behave documentation.

中没有对此的解释

下面是不用 @fixture 的方法,只需使用 before_tag 钩子即可:

#!/usr/bin/env python
# FILE: features/environment.py

import logging
from behave.runner import Context
from behave.model import Tag
from pathlib import Path

logger = logging.getLogger(__name__)


def rename_file(origin: Path, target: Path) -> tuple[Path, Path]:
    """
    Will rename the `origin` to `target`, replaces existing `target`
    """
    origin.touch()
    backup = origin.replace(target)
    logger.info(f"File {str(origin)} renamed to {str(target)}")
    return origin, backup


def before_tag(context: Context, tag: Tag):
    if tag == "backup.file.important.txt":
        file = Path.home() / "important.txt"
        backup = file.with_suffix(".backup")
        context.file, context.backup_file = rename_file(file, backup)
        context.add_cleanup(rename_file, context.backup_file, context.file)
#!/usr/bin/env python
# File features/steps/file_ops.py

from pathlib import Path
from behave import given
from behave import when
from behave import then
from behave.runner import Context
import logging

logger = logging.getLogger(__name__)


@given("the file exists")
def step_impl(context: Context):
    logger.info(f"Touching file")
    context.file.touch()


@when("I append a line to the file")
def step_impl(context: Context):
    logger.info(f"Appending a line to file")
    context.appended = "Test line appended\n"
    with open(context.file, mode="a") as f:
        f.write(context.appended)


@then("the line appears at the end of the file")
def step_impl(context: Context):
    logger.info(f"Checking if line was appended")
    with open(context.file, mode="r") as f:
        for n, line in enumerate(f, start=1):
            logger.info(f"Line {n} is {line}")
        logger.info(f"Last line is '{line.strip()}'")
        assert line == context.appended

但是使用 behave 文档中 Realistic example 中描述的夹具和夹具注册表是更好的选择,因为您以后可能会得到更多 setup-cleanup 对。