Skip to content

Commit

Permalink
pytestplugin/hooks: combine multiple lg_feature markers instead of ov…
Browse files Browse the repository at this point in the history
…erwriting previous ones

pytest allows setting markers via function decorators [1], class
decorators [2] and "pytestmark" global to mark whole modules [2].
Additionally, each of these variants can specify multiple markers.

labgrid's pytest plugin considered only the closest marker. Change that
to allow combinations of multiple markers.

This allows use cases like:

  import pytest

  pytestmark = pytest.mark.lg_feature("watchdog")

  @pytest.mark.lg_feature("barebox")
  def test_watchdog_barebox(barebox):
      ..

Tests in this module are only run if the feature flag "watchdog" is
available. The specific test "test_watchdog_barebox" is only run if the
feature flag "barebox" is available additionally.

[1] https://docs.pytest.org/en/latest/example/markers.html#adding-a-custom-marker-from-a-plugin
[2] https://docs.pytest.org/en/latest/example/markers.html#marking-whole-classes-or-modules

Signed-off-by: Bastian Krause <[email protected]>
  • Loading branch information
Bastian-Krause committed Oct 29, 2021
1 parent f465656 commit 5dc0330
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 10 deletions.
2 changes: 2 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ Release 0.5.0 (unreleased)
New Features in 0.5.0
~~~~~~~~~~~~~~~~~~~~~
- Support for Eaton ePDU added, and can be used as a NetworkPowerPort.
- Consider a combination of multiple "lg_feature" markers instead of
considering only the closest marker.

Bug fixes in 0.5.0
~~~~~~~~~~~~~~~~~~
Expand Down
19 changes: 9 additions & 10 deletions labgrid/pytestplugin/hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,17 +61,16 @@ def pytest_collection_modifyitems(config, items):
have_feature = env.get_features() | env.get_target_features()

for item in items:
marker = item.get_closest_marker("lg_feature")
if not marker:
continue
want_feature = set()

arg = marker.args[0]
if isinstance(arg, str):
want_feature = set([arg])
elif isinstance(arg, list):
want_feature = set(arg)
else:
raise Exception("Unsupported feature argument type")
for marker in item.iter_markers("lg_feature"):
arg = marker.args[0]
if isinstance(arg, str):
want_feature.add(arg)
elif isinstance(arg, list):
want_feature.update(arg)
else:
raise Exception("Unsupported feature argument type")
missing_feature = want_feature - have_feature
if missing_feature:
if len(missing_feature) == 1:
Expand Down
67 changes: 67 additions & 0 deletions tests/test_flags.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,70 @@ def test(env):
spawn.expect(pexpect.EOF)
spawn.close()
assert spawn.exitstatus == 0

def test_match_multi_feature_source(tmpdir):
conf = tmpdir.join("config.yaml")
conf.write(
"""
targets:
test1:
features:
- test1
- test2
- test3
drivers: {}
"""
)
test = tmpdir.join("test.py")
test.write(
"""
import pytest
pytestmark = pytest.mark.lg_feature("test1")
@pytest.mark.lg_feature("test2")
class TestMulti:
@pytest.mark.lg_feature("test3")
def test(self, env):
assert True
"""
)

with pexpect.spawn(f'pytest --lg-env {conf} {test}') as spawn:
spawn.expect("1 passed")
spawn.expect(pexpect.EOF)
spawn.close()
assert spawn.exitstatus == 0

def test_skip_multi_feature_source(tmpdir):
conf = tmpdir.join("config.yaml")
conf.write(
"""
targets:
test1:
features:
- test1
- test3
drivers: {}
"""
)
test = tmpdir.join("test.py")
test.write(
"""
import pytest
pytestmark = pytest.mark.lg_feature("test1")
@pytest.mark.lg_feature("test2")
class TestMulti:
@pytest.mark.lg_feature("test3")
def test(self, env):
assert True
"""
)

with pexpect.spawn(f'pytest --lg-env {conf} {test}') as spawn:
spawn.expect("1 skipped")
spawn.expect(pexpect.EOF)
spawn.close()
assert spawn.exitstatus == 0

0 comments on commit 5dc0330

Please sign in to comment.