Skip to content

Commit

Permalink
Add ability to automatically collect *.feature files
Browse files Browse the repository at this point in the history
  • Loading branch information
uriyyo committed Dec 18, 2019
1 parent f3b92bd commit 9c08e32
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 6 deletions.
30 changes: 30 additions & 0 deletions pytest_bdd/bdd_module.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import sys

try:
from types import ModuleType
except ImportError:
ModuleType = type(sys)

from _pytest.python import Module
from .scenario import scenarios


class PytestBDDModule(Module):
"""
Class that represents *.feature file as python module
"""

def _getobj(self):
# Add _test suffix to module name
module_name = self.nodeid.replace("/", ".").rsplit(".", 1)[0] + "_test"

# Create dummy module to store tests
module = ModuleType(
name=module_name, doc="Autogenerated python module for {!r} feature file".format(str(self.fspath))
)
sys.modules[module_name] = module

# Add scenarios for dummy module
scenarios(self.fspath.basename, features_base_dir=self.fspath.dirname, module=module)

return module
10 changes: 10 additions & 0 deletions pytest_bdd/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from . import generation
from . import reporting
from . import gherkin_terminal_reporter
from .bdd_module import PytestBDDModule
from .utils import CONFIG_STACK


Expand Down Expand Up @@ -36,6 +37,7 @@ def pytest_addoption(parser):
def add_bdd_ini(parser):
parser.addini("bdd_features_base_dir", "Base features directory.")
parser.addini("bdd_strict_gherkin", "Parse features to be strict gherkin.", type="bool", default=True)
parser.addini("bdd_auto_collect", "To automatically collect feature files.", type="bool", default=False)


@pytest.mark.trylast
Expand Down Expand Up @@ -106,3 +108,11 @@ def item_key(item):
return (item.reportinfo()[:2], declaration_order)

items.sort(key=item_key)


def pytest_collect_file(path, parent):
"""
Automatically collect *.feature files and create test modules for them.
"""
if CONFIG_STACK[-1].getini("bdd_auto_collect") and path.ext == ".feature":
return PytestBDDModule(path, parent)
7 changes: 5 additions & 2 deletions pytest_bdd/scenario.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,8 +322,11 @@ def scenarios(*feature_paths, **kwargs):
:param *feature_paths: feature file paths to use for scenarios
"""
frame = inspect.stack()[1]
module = inspect.getmodule(frame[0])
if "module" in kwargs:
module = kwargs.pop("module")
else:
frame = inspect.stack()[1]
module = inspect.getmodule(frame[0])

features_base_dir = kwargs.get("features_base_dir")
if features_base_dir is None:
Expand Down
8 changes: 4 additions & 4 deletions pytest_bdd/scripts.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ def migrate_tests_in_file(file_path):
new_content = new_content.rstrip("\n") + "\n"
fd.seek(0)
fd.write(new_content)
print("migrated: {0}".format(file_path))
print ("migrated: {0}".format(file_path))
else:
print("skipped: {0}".format(file_path))
print ("skipped: {0}".format(file_path))
except IOError:
pass

Expand All @@ -50,9 +50,9 @@ def print_generated_code(args):
features, scenarios, steps = parse_feature_files(args.files)
code = generate_code(features, scenarios, steps)
if six.PY2:
print(code.encode("utf-8"))
print (code.encode("utf-8"))
else:
print(code)
print (code)


def main():
Expand Down
39 changes: 39 additions & 0 deletions tests/feature/test_auto_collect.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"""Auto collect tests."""
import pytest

import textwrap


@pytest.fixture
def auto_collect_test_dir(testdir):
dirname = "test_auto_collect"
tests = testdir.mkpydir(dirname)

tests.join("foo.feature").write(
textwrap.dedent(
r"""
Feature: The feature
Scenario: Some scenario
"""
)
)


def test_auto_collect_tests(auto_collect_test_dir, testdir):
testdir.makeini(
"""
[pytest]
bdd_auto_collect=true
"""
)

result = testdir.runpytest()

result.stdout.fnmatch_lines("collected 1 item")
result.assert_outcomes(passed=1)


def test_auto_collect_tests_disabled(auto_collect_test_dir, testdir):
result = testdir.runpytest()

result.stdout.fnmatch_lines("collected 0 items")

0 comments on commit 9c08e32

Please sign in to comment.