Skip to content

Commit b18a9de

Browse files
Merge pull request #2892 from nicoddemus/merge-master-into-features
Merge upstream/master into features
2 parents d7e8eee + f3a119c commit b18a9de

File tree

19 files changed

+215
-59
lines changed

19 files changed

+215
-59
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ Dave Hunt
4747
David Díaz-Barquero
4848
David Mohr
4949
David Vierra
50+
Daw-Ran Liou
5051
Denis Kirisov
5152
Diego Russo
5253
Dmitry Dygalo

_pytest/assertion/rewrite.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -591,23 +591,26 @@ def run(self, mod):
591591
# docstrings and __future__ imports.
592592
aliases = [ast.alias(py.builtin.builtins.__name__, "@py_builtins"),
593593
ast.alias("_pytest.assertion.rewrite", "@pytest_ar")]
594-
expect_docstring = True
594+
doc = getattr(mod, "docstring", None)
595+
expect_docstring = doc is None
596+
if doc is not None and self.is_rewrite_disabled(doc):
597+
return
595598
pos = 0
596-
lineno = 0
599+
lineno = 1
597600
for item in mod.body:
598601
if (expect_docstring and isinstance(item, ast.Expr) and
599602
isinstance(item.value, ast.Str)):
600603
doc = item.value.s
601-
if "PYTEST_DONT_REWRITE" in doc:
602-
# The module has disabled assertion rewriting.
604+
if self.is_rewrite_disabled(doc):
603605
return
604-
lineno += len(doc) - 1
605606
expect_docstring = False
606607
elif (not isinstance(item, ast.ImportFrom) or item.level > 0 or
607608
item.module != "__future__"):
608609
lineno = item.lineno
609610
break
610611
pos += 1
612+
else:
613+
lineno = item.lineno
611614
imports = [ast.Import([alias], lineno=lineno, col_offset=0)
612615
for alias in aliases]
613616
mod.body[pos:pos] = imports
@@ -633,6 +636,9 @@ def run(self, mod):
633636
not isinstance(field, ast.expr)):
634637
nodes.append(field)
635638

639+
def is_rewrite_disabled(self, docstring):
640+
return "PYTEST_DONT_REWRITE" in docstring
641+
636642
def variable(self):
637643
"""Get a new variable."""
638644
# Use a character invalid in python identifiers to avoid clashing.

_pytest/doctest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ def repr_failure(self, excinfo):
127127
lines = ["%03d %s" % (i + test.lineno + 1, x)
128128
for (i, x) in enumerate(lines)]
129129
# trim docstring error lines to 10
130-
lines = lines[example.lineno - 9:example.lineno + 1]
130+
lines = lines[max(example.lineno - 9, 0):example.lineno + 1]
131131
else:
132132
lines = ['EXAMPLE LOCATION UNKNOWN, not showing all tests of that example']
133133
indent = '>>>'

_pytest/mark.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,8 +293,9 @@ def _check(self, name):
293293
pass
294294
self._markers = l = set()
295295
for line in self._config.getini("markers"):
296-
beginning = line.split(":", 1)
297-
x = beginning[0].split("(", 1)[0]
296+
marker, _ = line.split(":", 1)
297+
marker = marker.rstrip()
298+
x = marker.split("(", 1)[0]
298299
l.add(x)
299300
if name not in self._markers:
300301
raise AttributeError("%r not a registered marker" % (name,))

changelog/1505.doc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Introduce a dedicated section about conftest.py.

changelog/2658.doc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Append example for pytest.param in the example/parametrize document.

changelog/2856.bugfix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Strip whitespace from marker names when reading them from INI config.

changelog/2882.bugfix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Show full context of doctest source in the pytest output, if the lineno of failed example in the docstring is < 9.

doc/en/assert.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,8 @@ the ``pytest_assertrepr_compare`` hook.
209209
.. autofunction:: _pytest.hookspec.pytest_assertrepr_compare
210210
:noindex:
211211

212-
As an example consider adding the following hook in a conftest.py which
213-
provides an alternative explanation for ``Foo`` objects::
212+
As an example consider adding the following hook in a :ref:`conftest.py <conftest.py>`
213+
file which provides an alternative explanation for ``Foo`` objects::
214214

215215
# content of conftest.py
216216
from test_foocompare import Foo

doc/en/example/parametrize.rst

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,4 +485,54 @@ of our ``test_func1`` was skipped. A few notes:
485485
values as well.
486486

487487

488+
Set marks or test ID for individual parametrized test
489+
--------------------------------------------------------------------
490+
491+
Use ``pytest.param`` to apply marks or set test ID to individual parametrized test.
492+
For example::
493+
494+
# content of test_pytest_param_example.py
495+
import pytest
496+
@pytest.mark.parametrize('test_input,expected', [
497+
('3+5', 8),
498+
pytest.param('1+7', 8,
499+
marks=pytest.mark.basic),
500+
pytest.param('2+4', 6,
501+
marks=pytest.mark.basic,
502+
id='basic_2+4'),
503+
pytest.param('6*9', 42,
504+
marks=[pytest.mark.basic, pytest.mark.xfail],
505+
id='basic_6*9'),
506+
])
507+
def test_eval(test_input, expected):
508+
assert eval(test_input) == expected
509+
510+
In this example, we have 4 parametrized tests. Except for the first test,
511+
we mark the rest three parametrized tests with the custom marker ``basic``,
512+
and for the fourth test we also use the built-in mark ``xfail`` to indicate this
513+
test is expected to fail. For explicitness, we set test ids for some tests.
514+
515+
Then run ``pytest`` with verbose mode and with only the ``basic`` marker::
516+
517+
pytest -v -m basic
518+
============================================ test session starts =============================================
519+
platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
520+
rootdir: $REGENDOC_TMPDIR, inifile:
521+
collected 4 items
522+
523+
test_pytest_param_example.py::test_eval[1+7-8] PASSED
524+
test_pytest_param_example.py::test_eval[basic_2+4] PASSED
525+
test_pytest_param_example.py::test_eval[basic_6*9] xfail
526+
========================================== short test summary info ===========================================
527+
XFAIL test_pytest_param_example.py::test_eval[basic_6*9]
528+
529+
============================================= 1 tests deselected =============================================
530+
531+
As the result:
488532

533+
- Four tests were collected
534+
- One test was deselected because it doesn't have the ``basic`` mark.
535+
- Three tests with the ``basic`` mark was selected.
536+
- The test ``test_eval[1+7-8]`` passed, but the name is autogenerated and confusing.
537+
- The test ``test_eval[basic_2+4]`` passed.
538+
- The test ``test_eval[basic_6*9]`` was expected to fail and did fail.

0 commit comments

Comments
 (0)