From ce83eb2a1d93cef962f8ccb7e7c5c93562a74cc5 Mon Sep 17 00:00:00 2001 From: Anatoly Bubenkov Date: Tue, 28 May 2013 16:41:45 +0200 Subject: [PATCH 1/5] base path for feature files --- README.md | 22 ++++++++++++++++++++++ pytest_bdd/scenario.py | 9 +++++++-- tests/feature/test_feature_path.py | 27 +++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 tests/feature/test_feature_path.py diff --git a/README.md b/README.md index 25f3b68..8d31a37 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ BDD library for the py.test runner [![Build Status](https://api.travis-ci.org/olegpidsadnyi/pytest-bdd.png)](https://travis-ci.org/olegpidsadnyi/pytest-bdd) + Install pytest-bdd ================= @@ -85,6 +86,7 @@ author of the article, but article should have some default author. Given I'm the admin And there is an article + Reuse fixtures ================ @@ -129,6 +131,26 @@ test_common.py: There are no definitions of the steps in the test file. They were collected from the parent conftests. + +Feature file paths +================== + +But default, pytest-bdd will use current module's path as base path for finding feature files, but this behaviour can +be changed by having fixture named 'pytest_bdd_feature_path' which should return the new base path. + +test_publish_article.py: + + import pytest + from pytest_bdd import scenario + + + @pytest.fixture + def pytest_bdd_feature_path(): + return '/home/user/projects/foo.bar/features' + + test_publish = scenario('publish_article.feature', 'Publishing the article') + + Subplugins ========== diff --git a/pytest_bdd/scenario.py b/pytest_bdd/scenario.py index 7ed2cde..0cc7abb 100644 --- a/pytest_bdd/scenario.py +++ b/pytest_bdd/scenario.py @@ -10,7 +10,6 @@ test_publish_article = scenario( scenario_name='Publishing the article', ) """ - import inspect from os import path as op @@ -26,7 +25,13 @@ def scenario(feature_name, scenario_name): def _scenario(request): # Get the feature - feature_path = op.abspath(op.join(op.dirname(request.module.__file__), feature_name)) + try: + base_path = request.getfuncargvalue('pytest_bdd_feature_path') + except LookupError: + # TODO: add concrete exception type, for now it's not clear how to import FixtureLookupErrorRepr from pytest + base_path = op.dirname(request.module.__file__) + + feature_path = op.abspath(op.join(base_path, feature_name)) feature = Feature.get_feature(feature_path) # Get the scenario diff --git a/tests/feature/test_feature_path.py b/tests/feature/test_feature_path.py new file mode 100644 index 0000000..dbf4eff --- /dev/null +++ b/tests/feature/test_feature_path.py @@ -0,0 +1,27 @@ +"""Test wrong feature syntax.""" +import os.path + +import pytest + +from pytest_bdd import scenario + + +@pytest.fixture(params=[ + 'When step can be the first', +]) +def scenario_name(request): + return request.param + + +@pytest.fixture +def pytest_bdd_feature_path(): + return '/does/not/exist' + + +def test_feature_path(request, scenario_name): + """Test feature path.""" + sc = scenario('steps.feature', scenario_name) + with pytest.raises(IOError) as exc: + sc(request) + + assert exc.value.filename == os.path.join('/does/not/exist/', 'steps.feature') From 528a36d81e504dc0a7b724268e13c20fa0025594 Mon Sep 17 00:00:00 2001 From: Anatoly Bubenkov Date: Tue, 28 May 2013 16:50:41 +0200 Subject: [PATCH 2/5] base path for feature files --- tests/feature/test_feature_path.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/feature/test_feature_path.py b/tests/feature/test_feature_path.py index dbf4eff..3ded85e 100644 --- a/tests/feature/test_feature_path.py +++ b/tests/feature/test_feature_path.py @@ -24,4 +24,4 @@ def test_feature_path(request, scenario_name): with pytest.raises(IOError) as exc: sc(request) - assert exc.value.filename == os.path.join('/does/not/exist/', 'steps.feature') + assert os.path.join('/does/not/exist/', 'steps.feature') in str(exc.value) From 106e5633db8d0609b5afe414222a5213dd0b49ce Mon Sep 17 00:00:00 2001 From: Anatoly Bubenkov Date: Tue, 28 May 2013 17:11:47 +0200 Subject: [PATCH 3/5] base path for feature files --- pytest_bdd/scenario.py | 7 +------ setup.py | 6 ++++++ tests/conftest.py | 1 + tests/feature/test_feature_path.py | 2 +- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/pytest_bdd/scenario.py b/pytest_bdd/scenario.py index 0cc7abb..281ee7e 100644 --- a/pytest_bdd/scenario.py +++ b/pytest_bdd/scenario.py @@ -25,12 +25,7 @@ def scenario(feature_name, scenario_name): def _scenario(request): # Get the feature - try: - base_path = request.getfuncargvalue('pytest_bdd_feature_path') - except LookupError: - # TODO: add concrete exception type, for now it's not clear how to import FixtureLookupErrorRepr from pytest - base_path = op.dirname(request.module.__file__) - + base_path = request.getfuncargvalue('pytestbdd_feature_path') feature_path = op.abspath(op.join(base_path, feature_name)) feature = Feature.get_feature(feature_path) diff --git a/setup.py b/setup.py index 1dd26c8..c820ecb 100755 --- a/setup.py +++ b/setup.py @@ -29,6 +29,12 @@ setup( install_requires=[ 'pytest', ], + # the following makes a plugin available to py.test + entry_points = { + 'pytest11': [ + 'pytest-bdd = pytest_bdd.plugin', + ] + }, tests_require=['mock'], packages=['pytest_bdd'], ) diff --git a/tests/conftest.py b/tests/conftest.py index 15aa0f4..a6f9fc0 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,6 +1,7 @@ """Configuration for pytest runner.""" from pytest_bdd import given, when +from pytest_bdd.plugin import pytestbdd_feature_path pytest_plugins = 'pytester' diff --git a/tests/feature/test_feature_path.py b/tests/feature/test_feature_path.py index 3ded85e..b229aab 100644 --- a/tests/feature/test_feature_path.py +++ b/tests/feature/test_feature_path.py @@ -14,7 +14,7 @@ def scenario_name(request): @pytest.fixture -def pytest_bdd_feature_path(): +def pytestbdd_feature_path(): return '/does/not/exist' From c4d110413da73284afa4b72b51d698e85ee20f54 Mon Sep 17 00:00:00 2001 From: Anatoly Bubenkov Date: Tue, 28 May 2013 17:12:00 +0200 Subject: [PATCH 4/5] base path for feature files --- pytest_bdd/plugin.py | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 pytest_bdd/plugin.py diff --git a/pytest_bdd/plugin.py b/pytest_bdd/plugin.py new file mode 100644 index 0000000..32ef3f1 --- /dev/null +++ b/pytest_bdd/plugin.py @@ -0,0 +1,8 @@ +import os.path + +import pytest + + +@pytest.fixture +def pytestbdd_feature_path(request): + return os.path.dirname(request.module.__file__) From dc3896cef6451bcd6a3d2abe817d5ade2bbd2e3c Mon Sep 17 00:00:00 2001 From: Anatoly Bubenkov Date: Tue, 28 May 2013 23:09:09 +0200 Subject: [PATCH 5/5] Fix doc typo, rename the base dir fixture, avoid overfixturing the functions --- README.md | 4 ++-- pytest_bdd/plugin.py | 4 +++- pytest_bdd/scenario.py | 2 +- pytest_bdd/steps.py | 4 +++- tests/conftest.py | 2 +- .../{test_feature_path.py => test_feature_base_dir.py} | 6 +++--- 6 files changed, 13 insertions(+), 9 deletions(-) rename tests/feature/{test_feature_path.py => test_feature_base_dir.py} (82%) diff --git a/README.md b/README.md index 8d31a37..e165f3f 100644 --- a/README.md +++ b/README.md @@ -136,7 +136,7 @@ Feature file paths ================== But default, pytest-bdd will use current module's path as base path for finding feature files, but this behaviour can -be changed by having fixture named 'pytest_bdd_feature_path' which should return the new base path. +be changed by having fixture named 'pytestbdd_feature_base_dir' which should return the new base path. test_publish_article.py: @@ -145,7 +145,7 @@ test_publish_article.py: @pytest.fixture - def pytest_bdd_feature_path(): + def pytestbdd_feature_base_dir(): return '/home/user/projects/foo.bar/features' test_publish = scenario('publish_article.feature', 'Publishing the article') diff --git a/pytest_bdd/plugin.py b/pytest_bdd/plugin.py index 32ef3f1..70ade2e 100644 --- a/pytest_bdd/plugin.py +++ b/pytest_bdd/plugin.py @@ -1,8 +1,10 @@ +"""Pytest plugin entry point. Used for any fixtures needed.""" + import os.path import pytest @pytest.fixture -def pytestbdd_feature_path(request): +def pytestbdd_feature_base_dir(request): return os.path.dirname(request.module.__file__) diff --git a/pytest_bdd/scenario.py b/pytest_bdd/scenario.py index 281ee7e..fed9485 100644 --- a/pytest_bdd/scenario.py +++ b/pytest_bdd/scenario.py @@ -25,7 +25,7 @@ def scenario(feature_name, scenario_name): def _scenario(request): # Get the feature - base_path = request.getfuncargvalue('pytestbdd_feature_path') + base_path = request.getfuncargvalue('pytestbdd_feature_base_dir') feature_path = op.abspath(op.join(base_path, feature_name)) feature = Feature.get_feature(feature_path) diff --git a/pytest_bdd/steps.py b/pytest_bdd/steps.py index 7579463..870764e 100644 --- a/pytest_bdd/steps.py +++ b/pytest_bdd/steps.py @@ -107,7 +107,9 @@ def _step_decorator(step_type, step_name): frame = inspect.stack()[1] module = inspect.getmodule(frame[0]) if step_type == GIVEN: - func = pytest.fixture(func) + if not hasattr(func, '_pytestfixturefunction'): + # avoid overfixturing of a fixture + func = pytest.fixture(func) step_func = lambda request: request.getfuncargvalue(func.func_name) step_func.__name__ = step_name diff --git a/tests/conftest.py b/tests/conftest.py index a6f9fc0..2063893 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,7 +1,7 @@ """Configuration for pytest runner.""" from pytest_bdd import given, when -from pytest_bdd.plugin import pytestbdd_feature_path +from pytest_bdd.plugin import pytestbdd_feature_base_dir pytest_plugins = 'pytester' diff --git a/tests/feature/test_feature_path.py b/tests/feature/test_feature_base_dir.py similarity index 82% rename from tests/feature/test_feature_path.py rename to tests/feature/test_feature_base_dir.py index b229aab..e8adcc9 100644 --- a/tests/feature/test_feature_path.py +++ b/tests/feature/test_feature_base_dir.py @@ -1,4 +1,4 @@ -"""Test wrong feature syntax.""" +"""Test feature base dir.""" import os.path import pytest @@ -14,12 +14,12 @@ def scenario_name(request): @pytest.fixture -def pytestbdd_feature_path(): +def pytestbdd_feature_base_dir(): return '/does/not/exist' def test_feature_path(request, scenario_name): - """Test feature path.""" + """Test feature base dir.""" sc = scenario('steps.feature', scenario_name) with pytest.raises(IOError) as exc: sc(request)