diff --git a/aloe/fs.py b/aloe/fs.py index 6d13e33e..84ea9ae6 100644 --- a/aloe/fs.py +++ b/aloe/fs.py @@ -18,6 +18,9 @@ from aloe.exceptions import StepDiscoveryError +GHERKIN_FEATURES_DIR_NAME = 'GHERKIN_FEATURES_DIR_NAME' + + def path_to_module_name(filename): """Convert a path to a file to a Python module name.""" @@ -65,16 +68,39 @@ def find_and_load_step_definitions(cls, dir_): exc ) + @classmethod + def features_dirname(cls): + """ + Set the name of the features directory. + It is possible to change the name by setting the environment variable: + GHERKIN_FEATURES_DIR_NAME = 'gherkin_features' + """ + + env = os.environ + features_dirname = env.get(GHERKIN_FEATURES_DIR_NAME, 'features') + + # check the dir name is not a path + if '/' in features_dirname: + raise_from( + StepDiscoveryError("%s cannot be a path: %s" % ( + GHERKIN_FEATURES_DIR_NAME, features_dirname)), + None + ) + + return features_dirname + @classmethod def find_feature_directories(cls, dir_): """ Locate directories to load features from. - The directories must be named 'features'; they must either reside + The directories should be named 'features'; they must either reside directly in the specified directory, or otherwise all their parents must be packages (have __init__.py files). """ + features_dirname = cls.features_dirname() + # A set of package directories discovered packages = set() @@ -85,8 +111,8 @@ def find_feature_directories(cls, dir_): if path == dir_ or path in packages: # Does this package have a feature directory? - if 'features' in dirs: - yield os.path.join(path, 'features') + if features_dirname in dirs: + yield os.path.join(path, features_dirname) else: # This is not a package, prune search diff --git a/tests/functional/test_step_loading.py b/tests/functional/test_step_loading.py index efe1f840..f47b9876 100644 --- a/tests/functional/test_step_loading.py +++ b/tests/functional/test_step_loading.py @@ -53,3 +53,47 @@ def test_all_features(self): 'submodule/features/third.feature', ) ]) + + def test_single_alternative_feature(self): + """ + Test running a single feature in the alternative features directory. + """ + + os.environ['GHERKIN_FEATURES_DIR_NAME'] = 'alternative_features' + + self.assert_feature_success('alternative_features/single.feature') + + del os.environ['GHERKIN_FEATURES_DIR_NAME'] + + def test_alternative_subdirectory_feature(self): + """ + Test running a feature in a subdirectory of the alternative features + directory. + """ + + os.environ['GHERKIN_FEATURES_DIR_NAME'] = 'alternative_features' + + self.assert_feature_success( + 'alternative_features/subdirectory/another.feature') + + del os.environ['GHERKIN_FEATURES_DIR_NAME'] + + def test_all_alternative_features(self): + """ + Test running all the features under the alternative features directory + without explicitly specifying them. + """ + + os.environ['GHERKIN_FEATURES_DIR_NAME'] = 'alternative_features' + + result = self.assert_feature_success() + + del os.environ['GHERKIN_FEATURES_DIR_NAME'] + + self.assertEqual(result.tests_run, [ + os.path.abspath(feature) for feature in ( + 'alternative_features/single.feature', + 'alternative_features/subdirectory/another.feature', + 'submodule/alternative_features/third.feature', + ) + ]) diff --git a/tests/step_definition_app/alternative_features/__init__.py b/tests/step_definition_app/alternative_features/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/step_definition_app/alternative_features/single.feature b/tests/step_definition_app/alternative_features/single.feature new file mode 100644 index 00000000..1878b4ac --- /dev/null +++ b/tests/step_definition_app/alternative_features/single.feature @@ -0,0 +1,5 @@ +Feature: Test loading feature from the root features directory + + Scenario: Use steps + Given I use alternative step one + And I use alternative step two diff --git a/tests/step_definition_app/alternative_features/steps/__init__.py b/tests/step_definition_app/alternative_features/steps/__init__.py new file mode 100644 index 00000000..299b4102 --- /dev/null +++ b/tests/step_definition_app/alternative_features/steps/__init__.py @@ -0,0 +1,3 @@ +""" +Step module for the test application. +""" diff --git a/tests/step_definition_app/alternative_features/steps/one.py b/tests/step_definition_app/alternative_features/steps/one.py new file mode 100644 index 00000000..b27e676f --- /dev/null +++ b/tests/step_definition_app/alternative_features/steps/one.py @@ -0,0 +1,12 @@ +""" +Part of steps for the tested application. +""" +# pylint:disable=unused-argument + +from aloe import step + + +@step(r'I use alternative step one') +def step_one(self): + """Dummy step.""" + pass diff --git a/tests/step_definition_app/alternative_features/steps/two.py b/tests/step_definition_app/alternative_features/steps/two.py new file mode 100644 index 00000000..c1b7cc98 --- /dev/null +++ b/tests/step_definition_app/alternative_features/steps/two.py @@ -0,0 +1,15 @@ +""" +Part of steps for the tested application. +""" + +# pylint:disable=unused-argument,unused-import + +from aloe import step + +from .one import step_one + + +@step(r'I use alternative step two') +def step_two(self): + """Dummy step.""" + pass diff --git a/tests/step_definition_app/alternative_features/subdirectory/another.feature b/tests/step_definition_app/alternative_features/subdirectory/another.feature new file mode 100644 index 00000000..4318aef9 --- /dev/null +++ b/tests/step_definition_app/alternative_features/subdirectory/another.feature @@ -0,0 +1,5 @@ +Feature: Test loading feature from a subdirectory + + Scenario: Use steps + Given I use alternative step one + And I use alternative step two diff --git a/tests/step_definition_app/submodule/alternative_features/third.feature b/tests/step_definition_app/submodule/alternative_features/third.feature new file mode 100644 index 00000000..46ccbb12 --- /dev/null +++ b/tests/step_definition_app/submodule/alternative_features/third.feature @@ -0,0 +1,5 @@ +Feature: Test loading feature from a submodule + + Scenario: Use steps + Given I use alternative step one + And I use alternative step two diff --git a/tests/unit/test_fs.py b/tests/unit/test_fs.py index 59ff7357..c7999357 100644 --- a/tests/unit/test_fs.py +++ b/tests/unit/test_fs.py @@ -7,9 +7,11 @@ from __future__ import division from __future__ import absolute_import +import os import unittest -from aloe.fs import path_to_module_name +from aloe.exceptions import StepDiscoveryError +from aloe.fs import FeatureLoader, path_to_module_name class PathToModuleNameTest(unittest.TestCase): @@ -29,3 +31,16 @@ def test_path_to_module_name(self): 'one.two', path_to_module_name('one/two/__init__.py') ) + + +class AlternativeFeaturesDirTest(unittest.TestCase): + """Test alternative features directory.""" + + def test_alternative_directory(self): + """Test alternative directory is not a path""" + + with self.assertRaises(StepDiscoveryError): + os.environ['GHERKIN_FEATURES_DIR_NAME'] = 'my/features' + FeatureLoader.features_dirname() + + del os.environ['GHERKIN_FEATURES_DIR_NAME']