Skip to content

Commit 0646548

Browse files
Merge branch 'master' into gherkin_reporter_parametrized_tests_fix
2 parents 256f6c6 + 72a8764 commit 0646548

28 files changed

+181
-228
lines changed

.travis.yml

Lines changed: 12 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,20 @@
1-
sudo: false
1+
dist: xenial
22
language: python
3-
python: "2.7"
3+
python:
4+
- "2.7"
5+
- "3.5"
6+
- "3.6"
7+
- "3.7"
8+
9+
install: pip install tox tox-travis
410

5-
matrix:
6-
include:
7-
- env: TOXENV=py27-pytestlatest-linters
8-
- env: TOXENV=py27-pytest29
9-
- env: TOXENV=py27-pytest30
10-
- env: TOXENV=py27-pytest31
11-
- env: TOXENV=py27-pytest32
12-
- env: TOXENV=py27-pytest33
13-
- env: TOXENV=py27-pytest34
14-
- env: TOXENV=py27-pytest35
15-
- env: TOXENV=py27-pytest36
16-
- env: TOXENV=py27-pytest37
17-
- env: TOXENV=py27-pytest38
18-
- env: TOXENV=py27-pytest39
19-
- env: TOXENV=py27-pytest310
20-
- env: TOXENV=py27-pytest40
21-
- env: TOXENV=py27-pytestlatest
22-
- env: TOXENV=py27-pytestlatest-xdist
23-
- env: TOXENV=py34-pytestlatest
24-
python: "3.4"
25-
- env: TOXENV=py35-pytestlatest
26-
python: "3.5"
27-
- env: TOXENV=py36-pytestlatest
28-
python: "3.6"
29-
- env: TOXENV=py37-pytestlatest
30-
python: "3.7"
31-
# Currently, python 3.7 is a little bit tricky to install:
32-
# https://github.com/travis-ci/travis-ci/issues/9069#issuecomment-425720905
33-
sudo: required
34-
dist: xenial
35-
- env: TOXENV=py27-pytestlatest-coveralls
36-
install:
37-
- pip install tox
3811
script: tox --recreate
12+
3913
branches:
4014
except:
4115
- /^\d/
16+
4217
notifications:
4318
email:
44-
45-
19+
20+

CHANGES.rst

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,24 @@
11
Changelog
22
=========
33

4+
Unreleased
5+
----------
6+
7+
3.1.1
8+
----------
9+
10+
- Allow unicode string in ``@given()`` step names when using python2.
11+
This makes the transition of projects from python 2 to 3 easier.
12+
13+
3.1.0
14+
----------
15+
16+
- Drop support for pytest < 3.3.2.
17+
- Step definitions generated by ``$ pytest-bdd generate`` will now raise ``NotImplementedError`` by default.
18+
- ``@given(...)`` no longer accepts regex objects. It was deprecated long ago.
19+
- Improve project testing by treating warnings as exceptions.
20+
- ``pytest_bdd_step_validation_error`` will now always receive ``step_func_args`` as defined in the signature.
21+
422
3.0.2
523
------
624

README.rst

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ Install pytest-bdd
3535
pip install pytest-bdd
3636

3737

38-
The minimum required version of pytest is 2.8.1.
38+
The minimum required version of pytest is 3.3.2
3939

4040

4141
Example
@@ -168,24 +168,24 @@ pass optional ``scope`` argument:
168168

169169
.. code-block:: python
170170
171-
@given('I have an article', scope='session')
171+
@given('there is an article', scope='session')
172172
def article(author):
173173
return create_test_article(author=author)
174174
175175
.. code-block:: gherkin
176176
177177
Scenario: I'm the author
178178
Given I'm an author
179-
And I have an article
179+
And there is an article
180180
181181
182182
Scenario: I'm the admin
183183
Given I'm the admin
184184
And there is an article
185185
186186
187-
For this example, step function for 'I have an article' given step will be executed once even though there are 2
188-
scenarios using it.
187+
In this example, the step function for the 'there is an article' given step will be executed once, even though there
188+
are 2 scenarios using it.
189189
Note that for other step types, it makes no sense to have scope larger than 'function' (the default) as they represent
190190
an action (when step), and assertion (then step).
191191

@@ -379,7 +379,7 @@ Multiline steps
379379
---------------
380380

381381
As Gherkin, pytest-bdd supports multiline steps
382-
(aka `PyStrings <http://docs.behat.org/guides/1.gherkin.html#pystrings>`_).
382+
(aka `PyStrings <http://behat.org/en/v3.0/user_guide/writing_scenarios.html#pystrings>`_).
383383
But in much cleaner and powerful way:
384384

385385
.. code-block:: gherkin
@@ -482,7 +482,7 @@ Scenario outlines
482482

483483
Scenarios can be parametrized to cover few cases. In Gherkin the variable
484484
templates are written using corner braces as <somevalue>.
485-
`Gherkin scenario outlines <http://docs.behat.org/guides/1.gherkin.html#scenario-outlines>`_ are supported by pytest-bdd
485+
`Gherkin scenario outlines <http://behat.org/en/v3.0/user_guide/writing_scenarios.html#scenario-outlines>`_ are supported by pytest-bdd
486486
exactly as it's described in be behave_ docs.
487487

488488
Example:
@@ -859,7 +859,7 @@ Backgrounds
859859

860860
It's often the case that to cover certain feature, you'll need multiple scenarios. And it's logical that the
861861
setup for those scenarios will have some common parts (if not equal). For this, there are `backgrounds`.
862-
pytest-bdd implements `Gherkin backgrounds <http://docs.behat.org/en/v2.5/guides/1.gherkin.html#backgrounds>`_ for
862+
pytest-bdd implements `Gherkin backgrounds <http://behat.org/en/v3.0/user_guide/writing_scenarios.html#backgrounds>`_ for
863863
features.
864864

865865
.. code-block:: gherkin
@@ -974,13 +974,13 @@ Using unicode in the feature files
974974
----------------------------------
975975

976976
As mentioned above, by default, utf-8 encoding is used for parsing feature files.
977-
For steps definition, you can both use unicode- and bytestrings equally.
978-
However, for argumented steps, if you need to use unicode symbols in it's regular expression, use `u` sign with regex:
977+
For steps definition, you should use unicode strings, which is the default in python 3.
978+
If you are on python 2, make sure you use unicode strings by prefixing them with the `u` sign.
979979

980980

981981
.. code-block:: python
982982
983-
@given(re.compile(u"у мене є рядок який містить '{0}'".format('(?P<content>.+)')))
983+
@given(parsers.re(u"у мене є рядок який містить '{0}'".format(u'(?P<content>.+)')))
984984
def there_is_a_string_with_content(content, string):
985985
"""Create string with unicode content."""
986986
string['content'] = content

pytest.ini

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[pytest]
2+
pep8maxlinelength=120
3+
addopts=-vvl
4+
filterwarnings =
5+
error
6+
ignore::DeprecationWarning

pytest_bdd/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
from pytest_bdd.steps import given, when, then
44
from pytest_bdd.scenario import scenario, scenarios
55

6-
__version__ = '3.0.2'
6+
__version__ = '3.1.1'
77

88
__all__ = [given.__name__, when.__name__, then.__name__, scenario.__name__, scenarios.__name__]

pytest_bdd/parsers.py

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,17 @@
11
"""Step parsers."""
22

33
from __future__ import absolute_import
4+
45
import re as base_re
5-
import warnings
66

77
import parse as base_parse
8-
from parse_type import cfparse as base_cfparse
9-
108
import six
9+
from parse_type import cfparse as base_cfparse
1110

1211
from .exceptions import InvalidStepParserError
1312

1413

15-
RE_TYPE = type(base_re.compile(''))
16-
17-
1814
class StepParser(object):
19-
2015
"""Parser of the individual step."""
2116

2217
def __init__(self, name):
@@ -35,7 +30,6 @@ def is_matching(self, name):
3530

3631

3732
class re(StepParser):
38-
3933
"""Regex step parser."""
4034

4135
def __init__(self, name, *args, **kwargs):
@@ -56,7 +50,6 @@ def is_matching(self, name):
5650

5751

5852
class parse(StepParser):
59-
6053
"""parse step parser."""
6154

6255
def __init__(self, name, *args, **kwargs):
@@ -80,7 +73,6 @@ def is_matching(self, name):
8073

8174

8275
class cfparse(parse):
83-
8476
"""cfparse step parser."""
8577

8678
def __init__(self, name, *args, **kwargs):
@@ -90,7 +82,6 @@ def __init__(self, name, *args, **kwargs):
9082

9183

9284
class string(StepParser):
93-
9485
"""Exact string step parser."""
9586

9687
def parse_arguments(self, name):
@@ -113,16 +104,9 @@ def get_parser(step_name):
113104
:return: step parser object
114105
:rtype: StepArgumentParser
115106
"""
116-
if isinstance(step_name, RE_TYPE):
117-
# backwards compartibility
118-
warn = (
119-
'pytest-bdd [{0}]: Direct usage of regex is deprecated. Please use pytest_bdd.parsers.re instead.'.format(
120-
step_name.pattern)
121-
)
122-
warnings.warn(warn)
123-
print(warn)
124-
return re(step_name.pattern, flags=step_name.flags)
125-
elif isinstance(step_name, six.string_types):
107+
if isinstance(step_name, six.string_types):
108+
if isinstance(step_name, six.binary_type): # Python 2 compatibility
109+
step_name = step_name.decode('utf-8')
126110
return string(step_name)
127111
elif not hasattr(step_name, 'is_matching') or not hasattr(step_name, 'parse_arguments'):
128112
raise InvalidStepParserError(step_name)

pytest_bdd/scenario.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
recreate_function,
3939
)
4040
from .types import GIVEN
41-
from .utils import CONFIG_STACK, get_args, get_fixture_value
41+
from .utils import CONFIG_STACK, get_args
4242

4343
if six.PY3: # pragma: no cover
4444
import runpy
@@ -70,7 +70,7 @@ def find_argumented_step_fixture_name(name, type_, fixturemanager, request=None)
7070
parser_name = get_step_fixture_name(parser.name, type_)
7171
if request:
7272
try:
73-
get_fixture_value(request, parser_name)
73+
request.getfixturevalue(parser_name)
7474
except pytest_fixtures.FixtureLookupError:
7575
continue
7676
return parser_name
@@ -88,12 +88,12 @@ def _find_step_function(request, step, scenario, encoding):
8888
"""
8989
name = step.name
9090
try:
91-
return get_fixture_value(request, get_step_fixture_name(name, step.type, encoding))
91+
return request.getfixturevalue(get_step_fixture_name(name, step.type, encoding))
9292
except pytest_fixtures.FixtureLookupError:
9393
try:
9494
name = find_argumented_step_fixture_name(name, step.type, request._fixturemanager, request)
9595
if name:
96-
return get_fixture_value(request, name)
96+
return request.getfixturevalue(name)
9797
raise
9898
except pytest_fixtures.FixtureLookupError:
9999
raise exceptions.StepDefinitionNotFoundError(
@@ -128,7 +128,7 @@ def _execute_step_function(request, scenario, step, step_func):
128128
kw["step_func_args"] = {}
129129
try:
130130
# Get the step argument values.
131-
kwargs = dict((arg, get_fixture_value(request, arg)) for arg in get_args(step_func))
131+
kwargs = dict((arg, request.getfixturevalue(arg)) for arg in get_args(step_func))
132132
kw["step_func_args"] = kwargs
133133

134134
request.config.hook.pytest_bdd_before_step_call(**kw)
@@ -188,6 +188,7 @@ def _execute_scenario(feature, scenario, request, encoding):
188188
step=step,
189189
step_func=step_func,
190190
exception=exception,
191+
step_func_args=dict((arg, request.getfixturevalue(arg)) for arg in get_args(step_func)),
191192
)
192193
raise
193194

pytest_bdd/steps.py

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,7 @@ def article(author):
4949
StepError,
5050
)
5151
from .parsers import get_parser
52-
from .utils import get_args, get_fixture_value, get_fixture_value_raw, set_fixture_value, get_request_fixture_defs, \
53-
get_request_fixture_names
52+
from .utils import get_args
5453

5554

5655
def get_step_fixture_name(name, type_, encoding=None):
@@ -82,11 +81,11 @@ def given(name, fixture=None, converters=None, scope='function', target_fixture=
8281
module = get_caller_module()
8382

8483
def step_func(request):
85-
return get_fixture_value(request, fixture)
84+
return request.getfixturevalue(fixture)
8685

8786
step_func.step_type = GIVEN
8887
step_func.converters = converters
89-
step_func.__name__ = name
88+
step_func.__name__ = force_encode(name, 'ascii')
9089
step_func.fixture = fixture
9190
func = pytest.fixture(scope=scope)(lambda: step_func)
9291
func.__doc__ = 'Alias for the "{0}" fixture.'.format(fixture)
@@ -162,7 +161,7 @@ def decorator(func):
162161
func = pytest.fixture(scope=scope)(func)
163162

164163
def step_func(request):
165-
result = get_fixture_value(request, func.__name__)
164+
result = request.getfixturevalue(func.__name__)
166165
if target_fixture:
167166
inject_fixture(request, target_fixture, result)
168167
return result
@@ -305,26 +304,21 @@ def inject_fixture(request, arg, value):
305304
fd = pytest_fixtures.FixtureDef(**fd_kwargs)
306305
fd.cached_result = (value, 0, None)
307306

308-
old_fd = get_request_fixture_defs(request).get(arg)
307+
old_fd = request._fixture_defs.get(arg)
309308
add_fixturename = arg not in request.fixturenames
310309

311-
old_value = get_fixture_value_raw(request, arg) # Compatibility with pytest < 3.3.2
312-
313310
def fin():
314311
request._fixturemanager._arg2fixturedefs[arg].remove(fd)
315-
get_request_fixture_defs(request)[arg] = old_fd
312+
request._fixture_defs[arg] = old_fd
316313

317314
if add_fixturename:
318-
get_request_fixture_names(request).remove(arg)
319-
320-
set_fixture_value(request, arg, old_value) # Compatibility with pytest < 3.3.2
315+
request._pyfuncitem._fixtureinfo.names_closure.remove(arg)
321316

322317
request.addfinalizer(fin)
323318

324319
# inject fixture definition
325320
request._fixturemanager._arg2fixturedefs.setdefault(arg, []).insert(0, fd)
326321
# inject fixture value in request cache
327-
get_request_fixture_defs(request)[arg] = fd
328-
set_fixture_value(request, arg, value)
322+
request._fixture_defs[arg] = fd
329323
if add_fixturename:
330-
get_request_fixture_names(request).append(arg)
324+
request._pyfuncitem._fixtureinfo.names_closure.append(arg)

pytest_bdd/templates/test.py.mak

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ def test_${ make_python_name(scenario.name)}():
2222
@${step.type}('${step.name}')
2323
def ${ make_python_name(step.name)}():
2424
"""${step.name}."""
25+
raise NotImplementedError
2526
% if not loop.last:
2627

2728

0 commit comments

Comments
 (0)