Wal*_*elt 5 python bdd pytest python-behave pytest-bdd
我想定义一个基于 PyTest-BDD 的场景大纲,其中包含多个示例。示例片段:
Scenario Outline: front to back validation
When tester executes access view sql query <sqlCommandProp> into av dataframe
And tester adds investment quant id to av dataframe
And tester reads raw file <fileNameProp> from datalake into raw dataframe
@raw2AccessValidation
Examples:
|sqlCommandProp|fileNameProp|
|sqlCommand | fileName |
@raw2AccessValidation2
Examples:
|sqlCommandProp|fileNameProp|
|eric | shane |
Run Code Online (Sandbox Code Playgroud)
我想为每个示例都有单独的标签,因为我可能不想运行所有示例。
我已经尝试了上面的方法,发现多个示例都可以。但是,我似乎无法识别不同的标签,因此我无法指定要运行这两个(或更多)中的哪一个。
我问是因为这可以用 java/cucumber 引擎完成。想知道我是否使用 pytest-bdd 遗漏了什么,做错了什么?
谢谢
基于这个问题,目前还不支持。
解决方案1:利用标记并将它们注册到 pytest 挂钩中
在上述问题得到解决之前,您可以选择使用 pytest 挂钩并手动注册标记。以下代码迭代所有已注册的测试项,并根据其各自的特征文件在其上注册新标记。它依赖于 pytest-bdd 库的几个内部属性,但它甚至在库内部合并该功能之前就可以有效运行:
# conftest.py
import re
from pathlib import Path
from typing import List
import pytest
def pytest_collection_modifyitems(config: pytest.Config, items: List[pytest.Item]):
for item in items:
if not hasattr(item, "_pyfuncitem") or not hasattr(item, "callspec"):
continue
feature = item._pyfuncitem._obj.__scenario__.feature
feature_content_lines = Path(feature.filename).read_text().splitlines()
parameters = list(item.callspec.params["_pytest_bdd_example"].values())
examples_start_line = None
for i, line in enumerate(feature_content_lines):
if "Examples:" in line:
examples_start_line = i
continue
elif re.match(r"[|\s]+{}[|\s]+".format(r"[|\s]+".join(parameters)), line):
break
if examples_start_line is None:
continue
tag_match = re.search(
r"@(?P<tag>\S+)", feature_content_lines[examples_start_line - 1]
)
if tag_match is None:
continue
tag = tag_match.group("tag")
item.add_marker(tag)
Run Code Online (Sandbox Code Playgroud)
考虑以下功能文件:
Feature: Scenario outlines
Scenario Outline: Outlined given, when, then
Given there are <start> cucumbers
When I eat <eat> cucumbers
Then I should have <left> cucumbers
@part1
Examples:
| start | eat | left |
| 12 | 5 | 7 |
| 12 | 4 | 8 |
@part2
Examples:
| start | eat | left |
| 11 | 5 | 6 |
Run Code Online (Sandbox Code Playgroud)
以及以下测试文件:
# test_scenario_outlines.py
from pytest_bdd import given, parsers, scenarios, then, when
scenarios("scenario_outlines.feature")
@given(parsers.parse("there are {start:d} cucumbers"), target_fixture="cucumbers")
def given_cucumbers(start):
return {"start": start, "eat": 0}
@when(parsers.parse("I eat {eat:d} cucumbers"))
def eat_cucumbers(cucumbers, eat):
cucumbers["eat"] += eat
@then(parsers.parse("I should have {left:d} cucumbers"))
def should_have_left_cucumbers(cucumbers, left):
assert cucumbers["start"] - cucumbers["eat"] == left
Run Code Online (Sandbox Code Playgroud)
您可以简单地使用标记来运行特定的示例记录:
pytest . -m part1
Run Code Online (Sandbox Code Playgroud)
pytest . -m part2
Run Code Online (Sandbox Code Playgroud)
注意:您应该注册标记以防止 pytest 警告。
解决方案 2:使用参数作为标签
您可以向参数表添加新列,并指定标签:
# scenario_outlines.feature
Feature: Scenario outlines
Scenario Outline: Outlined given, when, then
Given there are <start> cucumbers
When I eat <eat> cucumbers
Then I should have <left> cucumbers
Examples:
| start | eat | left | tag |
| 12 | 5 | 7 | part1 |
| 12 | 4 | 8 | part1 |
Examples:
| start | eat | left | tag |
| 11 | 5 | 6 | part2 |
Run Code Online (Sandbox Code Playgroud)
无需编辑Python测试文件或关注tag代码中的参数。相反,只需利用该-k选项有选择地选择具有特定标签值的记录:
pytest . -k part1
Run Code Online (Sandbox Code Playgroud)
pytest . -k part2
Run Code Online (Sandbox Code Playgroud)