Unknown marker with pytest-bdd only when parameter is declared

384 views Asked by At

When I declare a marker in pytest.ini having a parameter, this is not recognized in pytest-bdd feature file. Markers without parameters seem to work fine.

[pytest]
markers = 
    swr(issue1): link to Software Requirement
    smoke: Smoke Test component

Simple feature file works fine with @smoke:

Feature: Trivial Example
    @smoke
    Scenario: Add a number to another number
        Given 7 is set
        When 9 is added
        Then new value is 16

Fails with @swr("123"):

Feature: Trivial Example
    @swr("123")
    Scenario: Add a number to another number
        Given 7 is set
        When 9 is added
        Then new value is 16

Failure is a warning:

../../../../../.local/lib/python3.10/site-packages/pytest_bdd/plugin.py:127
  /home/parallels/.local/lib/python3.10/site-packages/pytest_bdd/plugin.py:127: PytestUnknownMarkWarning: Unknown pytest.mark.swr("123") - is this a typo?  You can register custom marks to avoid this warning - for details, see https://docs.pytest.org/en/stable/how-to/mark.html
    mark = getattr(pytest.mark, tag)
1

There are 1 answers

2
gold_cy On BEST ANSWER

Taking a look in the known issues in the repository I stumbled upon something that is related. The developer mentions there is a hook available which is seen here.

In the conftest.py we can then do the following:

from typing import Callable, cast
import pytest
import ast

def pytest_bdd_apply_tag(tag: str, function) -> Callable:
    tree = ast.parse(tag)
    body = tree.body[0].value
    if isinstance(body, ast.Call):
        name = body.func.id
        arg = body.args[0].value
        mark = getattr(pytest.mark, name).with_args(arg)
    else:
        mark = getattr(pytest.mark, tag)
    marked = mark(function)
    return cast(Callable, marked)

Then we can just register the marker as swr and the hook should automatically parametrize the function as needed. It uses ast to parse the marker and dynamically create the new marker. Shown below is what mark looks like when running with swr or swr("123").

platform darwin -- Python 3.9.6, pytest-7.2.0, pluggy-1.0.0
rootdir: ***, configfile: pytest.ini
plugins: bdd-6.1.1
collecting ... 
MarkDecorator(mark=Mark(name='swr', args=('123',), kwargs={}))
collected 1 item

platform darwin -- Python 3.9.6, pytest-7.2.0, pluggy-1.0.0
rootdir: ***, configfile: pytest.ini
plugins: bdd-6.1.1
collecting ... 
MarkDecorator(mark=Mark(name='swr', args=(), kwargs={}))
collected 1 item           

                                         

Take note of MarkDecorator in the output for each of the calls.