Skip to content

Commit 46644c3

Browse files
sliwinski-miloszyoutux
authored andcommitted
Add feature_base_dir and strict_gherkin params to scenario and scenarios
1 parent 92a7e59 commit 46644c3

File tree

3 files changed

+119
-38
lines changed

3 files changed

+119
-38
lines changed

pytest_bdd/scenario.py

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ def decorator(_pytestbdd_function):
263263

264264

265265
def scenario(feature_name, scenario_name, encoding="utf-8", example_converters=None,
266-
caller_module=None, caller_function=None):
266+
caller_module=None, caller_function=None, feature_base_dir=None, strict_gherkin=None):
267267
"""Scenario decorator.
268268
269269
:param str feature_name: Feature file name. Absolute or relative to the configured feature base path.
@@ -277,9 +277,11 @@ def scenario(feature_name, scenario_name, encoding="utf-8", example_converters=N
277277
caller_function = caller_function or get_caller_function()
278278

279279
# Get the feature
280-
base_dir = get_base_dir(caller_module)
281-
strict_gherkin = get_strict_gherkin()
282-
feature = Feature.get_feature(base_dir, feature_name, encoding=encoding, strict_gherkin=strict_gherkin)
280+
if feature_base_dir is None:
281+
feature_base_dir = get_feature_base_dir(caller_module)
282+
if strict_gherkin is None:
283+
strict_gherkin = get_strict_gherkin()
284+
feature = Feature.get_feature(feature_base_dir, feature_name, encoding=encoding, strict_gherkin=strict_gherkin)
283285

284286
# Get the sc_enario
285287
try:
@@ -309,20 +311,24 @@ def scenario(feature_name, scenario_name, encoding="utf-8", example_converters=N
309311
)
310312

311313

312-
def get_base_dir(caller_module):
314+
def get_feature_base_dir(caller_module):
313315
default_base_dir = os.path.dirname(caller_module.__file__)
314316
return get_from_ini('bdd_feature_base_dir', default_base_dir)
315317

316318

317-
def get_strict_gherkin():
318-
return get_from_ini('bdd_strict_gherkin', True)
319-
320-
321319
def get_from_ini(key, default):
320+
"""Get value from ini config. Return default if value has not been set.
321+
322+
Use if the default value is dynamic. Otherwise set default on addini call.
323+
"""
322324
value = pytest.config.getini(key)
323325
return value if value != '' else default
324326

325327

328+
def get_strict_gherkin():
329+
return pytest.config.getini('bdd_strict_gherkin')
330+
331+
326332
def make_python_name(string):
327333
"""Make python attribute name out of a given string."""
328334
string = re.sub(PYTHON_REPLACE_REGEX, "", string.replace(" ", "_"))
@@ -350,12 +356,19 @@ def scenarios(*feature_paths, **kwargs):
350356
"""
351357
frame = inspect.stack()[1]
352358
module = inspect.getmodule(frame[0])
353-
base_dir = get_base_dir(module)
354-
strict_gherkin = get_strict_gherkin()
359+
360+
feature_base_dir = kwargs.get('feature_base_dir')
361+
if feature_base_dir is None:
362+
feature_base_dir = get_feature_base_dir(module)
363+
364+
strict_gherkin = kwargs.get('strict_gherkin')
365+
if strict_gherkin is None:
366+
strict_gherkin = get_strict_gherkin()
367+
355368
abs_feature_paths = []
356369
for path in feature_paths:
357370
if not os.path.isabs(path):
358-
path = os.path.abspath(os.path.join(base_dir, path))
371+
path = os.path.abspath(os.path.join(feature_base_dir, path))
359372
abs_feature_paths.append(path)
360373
found = False
361374

Lines changed: 91 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,58 @@
11
"""Test feature base dir."""
22
import pytest
33

4+
NOT_EXISTING_FEATURE_PATHS = [
5+
'.',
6+
'/does/not/exist/',
7+
]
8+
49

510
@pytest.mark.parametrize(
6-
'base_dir', [
7-
'.',
8-
'/does/not/exist/',
9-
]
11+
'base_dir', NOT_EXISTING_FEATURE_PATHS
1012
)
1113
def test_feature_path_not_found(testdir, base_dir):
1214
"""Test feature base dir."""
1315
prepare_testdir(testdir, base_dir)
1416

15-
result = testdir.runpytest('-k', 'test_not_found')
16-
result.assert_outcomes(passed=1)
17+
result = testdir.runpytest('-k', 'test_not_found_by_ini')
18+
result.assert_outcomes(passed=2)
1719

1820

1921
def test_feature_path_ok(testdir):
2022
base_dir = 'features'
2123
prepare_testdir(testdir, base_dir)
2224

23-
result = testdir.runpytest('-k', 'test_ok')
24-
result.assert_outcomes(passed=1)
25+
result = testdir.runpytest('-k', 'test_ok_by_ini')
26+
result.assert_outcomes(passed=2)
27+
2528

29+
def test_feature_path_by_param_not_found(testdir):
30+
"""As param takes precendence even if ini config is correct it should fail
31+
if passed param is incorrect"""
32+
base_dir = 'features'
33+
prepare_testdir(testdir, base_dir)
2634

27-
def prepare_testdir(testdir, base_dir):
35+
result = testdir.runpytest('-k', 'test_not_found_by_param')
36+
result.assert_outcomes(passed=4)
37+
38+
39+
@pytest.mark.parametrize(
40+
'base_dir', NOT_EXISTING_FEATURE_PATHS
41+
)
42+
def test_feature_path_by_param_ok(testdir, base_dir):
43+
"""If ini config is incorrect but param path is fine it should be able
44+
to find features"""
45+
prepare_testdir(testdir, base_dir)
46+
47+
result = testdir.runpytest('-k', 'test_ok_by_param')
48+
result.assert_outcomes(passed=2)
49+
50+
51+
def prepare_testdir(testdir, ini_base_dir):
2852
testdir.makeini("""
2953
[pytest]
3054
bdd_feature_base_dir={}
31-
""".format(base_dir))
55+
""".format(ini_base_dir))
3256

3357
feature_file = testdir.mkdir('features').join('steps.feature')
3458
feature_file.write("""
@@ -37,24 +61,71 @@ def prepare_testdir(testdir, base_dir):
3761
""")
3862

3963
testdir.makepyfile("""
40-
import pytest
41-
from pytest_bdd import scenario
4264
import os.path
4365
66+
import pytest
67+
68+
from pytest_bdd import scenario, scenarios
69+
70+
FEATURE = 'steps.feature'
71+
72+
4473
@pytest.fixture(params=[
4574
'When scenario found',
4675
])
4776
def scenario_name(request):
4877
return request.param
4978
50-
def test_not_found(scenario_name):
51-
base_dir = '{}'
52-
print("BS: %s" % base_dir)
79+
80+
@pytest.mark.parametrize(
81+
'multiple', [True, False]
82+
)
83+
def test_not_found_by_ini(scenario_name, multiple):
5384
with pytest.raises(IOError) as exc:
54-
scenario('steps.feature', scenario_name)
55-
assert os.path.abspath(os.path.join(base_dir, 'steps.feature')) in str(exc.value)
85+
if multiple:
86+
scenarios(FEATURE)
87+
else:
88+
scenario(FEATURE, scenario_name)
89+
assert os.path.abspath(os.path.join('{}', FEATURE)) in str(exc.value)
90+
5691
57-
def test_ok(scenario_name):
92+
@pytest.mark.parametrize(
93+
'multiple', [True, False]
94+
)
95+
def test_ok_by_ini(scenario_name, multiple):
5896
# Shouldn't raise any exception
59-
scenario('steps.feature', scenario_name)
60-
""".format(base_dir))
97+
if multiple:
98+
scenarios(FEATURE)
99+
else:
100+
scenario(FEATURE, scenario_name)
101+
102+
103+
@pytest.mark.parametrize(
104+
'multiple', [True, False]
105+
)
106+
@pytest.mark.parametrize(
107+
'param_base_dir', [
108+
'.',
109+
'/does/not/exist/',
110+
]
111+
)
112+
def test_not_found_by_param(scenario_name, param_base_dir, multiple):
113+
with pytest.raises(IOError) as exc:
114+
if multiple:
115+
scenarios(FEATURE, feature_base_dir=param_base_dir)
116+
else:
117+
scenario(FEATURE, scenario_name, feature_base_dir=param_base_dir)
118+
assert os.path.abspath(os.path.join(param_base_dir, FEATURE)) in str(exc.value)
119+
120+
121+
@pytest.mark.parametrize(
122+
'multiple', [True, False]
123+
)
124+
def test_ok_by_param(scenario_name, multiple):
125+
# Shouldn't raise any exception no matter of bdd_feature_base_dir in ini
126+
if multiple:
127+
scenarios(FEATURE, feature_base_dir='features')
128+
else:
129+
scenario(FEATURE, scenario_name, feature_base_dir='features')
130+
131+
""".format(ini_base_dir))

tests/feature/test_wrong.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,13 @@ def then_nevermind():
3939
)
4040
@pytest.mark.parametrize('strict_gherkin', [True, False])
4141
@pytest.mark.parametrize('multiple', [True, False])
42-
@mock.patch.object(sys.modules['pytest_bdd.scenario'], 'get_strict_gherkin', return_value=True)
43-
def test_wrong(mocked_strict_gherkin, request, feature, scenario_name, strict_gherkin, multiple):
42+
def test_wrong(request, feature, scenario_name, strict_gherkin, multiple):
4443
"""Test wrong feature scenarios."""
45-
mocked_strict_gherkin.return_value = strict_gherkin
46-
4744
def declare_scenario():
4845
if multiple:
49-
scenarios(feature)
46+
scenarios(feature, strict_gherkin=strict_gherkin)
5047
else:
51-
@scenario(feature, scenario_name)
48+
@scenario(feature, scenario_name, strict_gherkin=strict_gherkin)
5249
def test_scenario():
5350
pass
5451

0 commit comments

Comments
 (0)