Merge branch 'master' into merge-master

# Conflicts:
#	AUTHORS
#	CHANGELOG.rst
#	_pytest/monkeypatch.py
#	_pytest/python.py
This commit is contained in:
Bruno Oliveira 2016-07-25 19:04:39 -03:00
commit c2864aba3d
18 changed files with 216 additions and 50 deletions

View File

@ -2,7 +2,10 @@ Thanks for submitting a PR, your contribution is really appreciated!
Here's a quick checklist that should be present in PRs:
- [ ] Target: for bug or doc fixes, target `master`; for new features, target `features`
- [ ] Make sure to include one or more tests for your change
- [ ] Add yourself to `AUTHORS`
- [ ] Add a new entry to the `CHANGELOG` (choose any open position to avoid merge conflicts with other PRs)
- [ ] Target: for bug or doc fixes, target `master`; for new features, target `features`;
- [ ] Make sure to include one or more tests for your change;
- [ ] Add yourself to `AUTHORS`;
- [ ] Add a new entry to `CHANGELOG.rst`
* Choose any open position to avoid merge conflicts with other PRs.
* Add a link to the issue you are fixing (if any) using RST syntax.
* The pytest team likes to have people to acknowledged in the `CHANGELOG`, so please add a thank note to yourself ("Thanks @user for the PR") and a link to your GitHub profile. It may sound weird thanking yourself, but otherwise a maintainer would have to do it manually before or after merging instead of just using GitHub's merge button. This makes it easier on the maintainers to merge PRs.

22
AUTHORS
View File

@ -8,8 +8,8 @@ Abhijeet Kasurde
Alexei Kozlenok
Anatoly Bubenkoff
Andreas Zeidler
Andy Freeland
Andrzej Ostrowski
Andy Freeland
Anthon van der Neut
Antony Lee
Armin Rigo
@ -17,6 +17,7 @@ Aron Curzon
Aviv Palivoda
Ben Webb
Benjamin Peterson
Bernard Pratz
Bob Ippolito
Brian Dorsey
Brian Okken
@ -38,7 +39,10 @@ Dave Hunt
David Díaz-Barquero
David Mohr
David Vierra
Diego Russo
Dmitry Dygalo
Edison Gustavo Muenz
Edoardo Batini
Eduardo Schettino
Elizaveta Shashkova
Endre Galaczi
@ -62,12 +66,14 @@ Jan Balster
Janne Vanhala
Jason R. Coombs
Javier Domingo Cansino
Javier Romero
John Towler
Jon Sonesen
Joshua Bronson
Jurko Gospodnetić
Justyna Janczyszyn
Katarzyna Jachim
Kale Kundert
Katarzyna Jachim
Kevin Cox
Lee Kamentsky
Lukas Bednar
@ -77,8 +83,8 @@ Marc Schlaich
Mark Abramowitz
Markus Unterwaditzer
Martijn Faassen
Martin Prusse
Martin K. Scherer
Martin Prusse
Matt Bachmann
Matt Williams
Michael Aquilina
@ -103,17 +109,17 @@ Ross Lawley
Russel Winder
Ryan Wooden
Samuele Pedroni
Simon Gomizelj
Stefan Farmbauer
Stefan Zimmermann
Stefano Taschini
Steffen Allner
Stephan Obermann
Tareq Alayan
Ted Xiao
Simon Gomizelj
Stefano Taschini
Stefan Farmbauer
Thomas Grainger
Tom Viner
Trevor Bekolay
Vasily Kuznetsov
Wouter van Ackooy
Bernard Pratz
Stefan Zimmermann

View File

@ -229,6 +229,12 @@ time or change existing behaviors in order to make them less surprising/more use
removed in pytest-4.0 (`#1684`_).
Thanks `@nicoddemus`_ for the PR.
* Raise helpful failure message, when requesting parametrized fixture at runtime,
e.g. with ``request.getfuncargvalue``. BACKWARD INCOMPAT: Previously these params
were simply never defined. So a fixture decorated like ``@pytest.fixture(params=[0, 1, 2])``
only ran once. Now a failure is raised. Fixes (`#460`_). Thanks to
`@nikratio`_ for bug report, `@RedBeardCode`_ and `@tomviner`_ for the PR.
* Passing a command-line string to ``pytest.main()`` is considered deprecated and scheduled
for removal in pytest-4.0. It is recommended to pass a list of arguments instead (`#1723`_).
@ -238,12 +244,19 @@ time or change existing behaviors in order to make them less surprising/more use
* ``optparse`` type usage now triggers DeprecationWarnings (`#1740`_).
* ``optparse`` backward compatibility supports float/complex types (`#457`_).
* Renamed the pytest ``pdb`` module (plugin) into ``debugging``.
* Better message in case of not using parametrized variable (see `#1539`_).
Thanks to `@tramwaj29`_ for the PR.
*
* Updated docstrings with a more uniform style.
* Add stderr write for ``pytest.exit(msg)`` during startup. Previously the message was never shown.
Thanks `@BeyondEvil`_ for reporting `#1210`_. Thanks to `@JonathonSonesen`_ and
`@tomviner`_ for PR.
*
@ -271,7 +284,18 @@ time or change existing behaviors in order to make them less surprising/more use
identify bugs in ``conftest.py`` files (`#1516`_). Thanks `@txomon`_ for
the PR.
*
* Add an 'E' to the first line of error messages from FixtureLookupErrorRepr.
Fixes `#717`_. Thanks `@blueyed`_ for reporting, `@eolo999`_ for the PR
and `@tomviner`_ for his guidance during EuroPython2016 sprint.
* Text documents without any doctests no longer appear as "skipped".
Thanks `@graingert`_ for reporting and providing a full PR (`#1580`_).
* Fixed collection of classes with custom ``__new__`` method.
Fixes `#1579`_. Thanks to `@Stranger6667`_ for the PR.
* Fixed scope overriding inside metafunc.parametrize (`#634`_).
Thanks to `@Stranger6667`_ for the PR.
*
@ -281,12 +305,7 @@ time or change existing behaviors in order to make them less surprising/more use
*
.. _#372: https://github.com/pytest-dev/pytest/issues/372
.. _#460: https://github.com/pytest-dev/pytest/pull/460
.. _#457: https://github.com/pytest-dev/pytest/issues/457
.. _#1740: https://github.com/pytest-dev/pytest/issues/1740
.. _#607: https://github.com/pytest-dev/pytest/issues/607
.. _#925: https://github.com/pytest-dev/pytest/issues/925
.. _#1210: https://github.com/pytest-dev/pytest/issues/1210
.. _#1235: https://github.com/pytest-dev/pytest/issues/1235
.. _#1351: https://github.com/pytest-dev/pytest/issues/1351
.. _#1421: https://github.com/pytest-dev/pytest/issues/1421
@ -305,9 +324,11 @@ time or change existing behaviors in order to make them less surprising/more use
.. _#1519: https://github.com/pytest-dev/pytest/pull/1519
.. _#1520: https://github.com/pytest-dev/pytest/pull/1520
.. _#1526: https://github.com/pytest-dev/pytest/pull/1526
.. _#1539: https://github.com/pytest-dev/pytest/issues/1539
.. _#1544: https://github.com/pytest-dev/pytest/issues/1544
.. _#1553: https://github.com/pytest-dev/pytest/issues/1553
.. _#1562: https://github.com/pytest-dev/pytest/issues/1562
.. _#1579: https://github.com/pytest-dev/pytest/issues/1579
.. _#1580: https://github.com/pytest-dev/pytest/pull/1580
.. _#1597: https://github.com/pytest-dev/pytest/pull/1597
.. _#1605: https://github.com/pytest-dev/pytest/issues/1605
@ -315,32 +336,40 @@ time or change existing behaviors in order to make them less surprising/more use
.. _#1618: https://github.com/pytest-dev/pytest/issues/1618
.. _#1619: https://github.com/pytest-dev/pytest/issues/1619
.. _#1626: https://github.com/pytest-dev/pytest/pull/1626
.. _#1668: https://github.com/pytest-dev/pytest/issues/1668
.. _#1627: https://github.com/pytest-dev/pytest/pull/1627
.. _#1628: https://github.com/pytest-dev/pytest/pull/1628
.. _#1629: https://github.com/pytest-dev/pytest/issues/1629
.. _#1632: https://github.com/pytest-dev/pytest/issues/1632
.. _#1633: https://github.com/pytest-dev/pytest/pull/1633
.. _#1664: https://github.com/pytest-dev/pytest/pull/1664
.. _#1668: https://github.com/pytest-dev/pytest/issues/1668
.. _#1684: https://github.com/pytest-dev/pytest/pull/1684
.. _#1723: https://github.com/pytest-dev/pytest/pull/1723
.. _#1539: https://github.com/pytest-dev/pytest/issues/1539
.. _#1740: https://github.com/pytest-dev/pytest/issues/1740
.. _#1749: https://github.com/pytest-dev/pytest/issues/1749
.. _#372: https://github.com/pytest-dev/pytest/issues/372
.. _#457: https://github.com/pytest-dev/pytest/issues/457
.. _#460: https://github.com/pytest-dev/pytest/pull/460
.. _#607: https://github.com/pytest-dev/pytest/issues/607
.. _#634: https://github.com/pytest-dev/pytest/issues/634
.. _#717: https://github.com/pytest-dev/pytest/issues/717
.. _#925: https://github.com/pytest-dev/pytest/issues/925
.. _@DRMacIver: https://github.com/DRMacIver
.. _@RedBeardCode: https://github.com/RedBeardCode
.. _@Vogtinator: https://github.com/Vogtinator
.. _@anntzer: https://github.com/anntzer
.. _@bagerard: https://github.com/bagerard
.. _@BeyondEvil: https://github.com/BeyondEvil
.. _@blueyed: https://github.com/blueyed
.. _@ceridwen: https://github.com/ceridwen
.. _@csaftoiu: https://github.com/csaftoiu
.. _@d6e: https://github.com/d6e
.. _@davehunt: https://github.com/davehunt
.. _@DRMacIver: https://github.com/DRMacIver
.. _@eolo999: https://github.com/eolo999
.. _@fengxx: https://github.com/fengxx
.. _@flub: https://github.com/flub
.. _@graingert: https://github.com/graingert
.. _@hartym: https://github.com/hartym
.. _@JonathonSonesen: https://github.com/JonathonSonesen
.. _@kalekundert: https://github.com/kalekundert
.. _@kvas-it: https://github.com/kvas-it
.. _@marscher: https://github.com/marscher
@ -353,12 +382,16 @@ time or change existing behaviors in order to make them less surprising/more use
.. _@olegpidsadnyi: https://github.com/olegpidsadnyi
.. _@omarkohl: https://github.com/omarkohl
.. _@palaviv: https://github.com/palaviv
.. _@RedBeardCode: https://github.com/RedBeardCode
.. _@sallner: https://github.com/sallner
.. _@sober7: https://github.com/sober7
.. _@Stranger6667: https://github.com/Stranger6667
.. _@tareqalayan: https://github.com/tareqalayan
.. _@taschini: https://github.com/taschini
.. _@txomon: https://github.com/txomon
.. _@tramwaj29: https://github.com/tramwaj29
.. _@txomon: https://github.com/txomon
.. _@Vogtinator: https://github.com/Vogtinator
2.9.2
=====
@ -392,8 +425,8 @@ time or change existing behaviors in order to make them less surprising/more use
.. _#510: https://github.com/pytest-dev/pytest/issues/510
.. _#1506: https://github.com/pytest-dev/pytest/pull/1506
.. _#1496: https://github.com/pytest-dev/pytest/issue/1496
.. _#1524: https://github.com/pytest-dev/pytest/issue/1524
.. _#1496: https://github.com/pytest-dev/pytest/issues/1496
.. _#1524: https://github.com/pytest-dev/pytest/pull/1524
.. _@prusse-martin: https://github.com/prusse-martin
.. _@astraw38: https://github.com/astraw38

View File

@ -157,7 +157,7 @@ error_capsysfderror = "cannot use capsys and capfd at the same time"
@pytest.fixture
def capsys(request):
"""enables capturing of writes to sys.stdout/sys.stderr and makes
"""Enable capturing of writes to sys.stdout/sys.stderr and make
captured output available via ``capsys.readouterr()`` method calls
which return a ``(out, err)`` tuple.
"""
@ -168,7 +168,7 @@ def capsys(request):
@pytest.fixture
def capfd(request):
"""enables capturing of writes to file descriptors 1 and 2 and makes
"""Enable capturing of writes to file descriptors 1 and 2 and make
captured output available via ``capfd.readouterr()`` method calls
which return a ``(out, err)`` tuple.
"""

View File

@ -673,8 +673,13 @@ class FixtureLookupErrorRepr(TerminalRepr):
#tw.line("FixtureLookupError: %s" %(self.argname), red=True)
for tbline in self.tblines:
tw.line(tbline.rstrip())
for line in self.errorstring.split("\n"):
tw.line(" " + line.strip(), red=True)
lines = self.errorstring.split("\n")
for line in lines:
if line == lines[0]:
prefix = 'E '
else:
prefix = ' '
tw.line(prefix + line.strip(), red=True)
tw.line()
tw.line("%s:%d" % (self.filename, self.firstlineno+1))

View File

@ -186,8 +186,8 @@ class _NodeReporter(object):
@pytest.fixture
def record_xml_property(request):
"""Fixture that adds extra xml properties to the tag for the calling test.
The fixture is callable with (name, value), with value being automatically
"""Add extra xml properties to the tag for the calling test.
The fixture is callable with ``(name, value)``, with value being automatically
xml-encoded.
"""
request.node.warn(

View File

@ -98,6 +98,10 @@ def wrap_session(config, doit):
raise
except KeyboardInterrupt:
excinfo = _pytest._code.ExceptionInfo()
if initstate < 2 and isinstance(
excinfo.value, pytest.exit.Exception):
sys.stderr.write('{0}: {1}\n'.format(
excinfo.typename, excinfo.value.msg))
config.hook.pytest_keyboard_interrupt(excinfo=excinfo)
session.exitstatus = EXIT_INTERRUPTED
except:

View File

@ -489,6 +489,10 @@ class Class(PyCollector):
self.warn("C1", "cannot collect test class %r because it has a "
"__init__ constructor" % self.obj.__name__)
return []
elif hasnew(self.obj):
self.warn("C1", "cannot collect test class %r because it has a "
"__new__ constructor" % self.obj.__name__)
return []
return [self._getcustomclass("Instance")(name="()", parent=self)]
def setup(self):
@ -506,8 +510,7 @@ class Class(PyCollector):
class Instance(PyCollector):
def _getobj(self):
obj = self.parent.obj()
return obj
return self.parent.obj()
def collect(self):
self.session._fixturemanager.parsefactories(self)
@ -622,8 +625,13 @@ class Generator(FunctionMixin, PyCollector):
def hasinit(obj):
init = getattr(obj, '__init__', None)
if init:
if init != object.__init__:
return True
return init != object.__init__
def hasnew(obj):
new = getattr(obj, '__new__', None)
if new:
return new != object.__new__
class CallSpec2(object):
@ -763,7 +771,7 @@ class Metafunc(fixtures.FuncargnamesCompatAttr):
It will also override any fixture-function defined scope, allowing
to set a dynamic scope using test context or configuration.
"""
from _pytest.fixtures import scopes
# individual parametrized argument sets can be wrapped in a series
# of markers in which case we unwrap the values and apply the mark
# at Function init
@ -794,10 +802,16 @@ class Metafunc(fixtures.FuncargnamesCompatAttr):
newmarks = newkeywords.setdefault(0, {})
newmarks[newmark.markname] = newmark
if scope is None:
scope = "function"
scopenum = fixtures.scopes.index(scope)
if self._arg2fixturedefs:
# Takes the most narrow scope from used fixtures
fixtures_scopes = [fixturedef[0].scope for fixturedef in self._arg2fixturedefs.values()]
for scope in reversed(scopes):
if scope in fixtures_scopes:
break
else:
scope = 'function'
scopenum = scopes.index(scope)
valtypes = {}
for arg in argnames:
if arg not in self.fixturenames:

View File

@ -108,7 +108,7 @@ def tmpdir_factory(request):
@pytest.fixture
def tmpdir(request, tmpdir_factory):
"""return a temporary directory path object
"""Return a temporary directory path object
which is unique to each test function invocation,
created as a sub directory of the base temporary
directory. The returned object is a `py.path.local`_

View File

@ -19,6 +19,7 @@ Full pytest documentation
recwarn
cache
plugins
nose
backwards-compatibility
contributing

View File

@ -24,7 +24,7 @@ Supported nose Idioms
* setup and teardown at module/class/method level
* SkipTest exceptions and markers
* setup/teardown decorators
* yield-based tests and their setup
* ``yield``-based tests and their setup
* ``__test__`` attribute on modules/classes/functions
* general usage of nose utilities
@ -51,5 +51,12 @@ Unsupported idioms / known issues
- nose-style doctests are not collected and executed correctly,
also doctest fixtures don't work.
- no nose-configuration is recognized
- no nose-configuration is recognized.
- ``yield``-based methods don't support ``setup`` properly because
the ``setup`` method is always called in the same class instance.
There are no plans to fix this currently because ``yield``-tests
are deprecated in pytest 3.0, with ``pytest.mark.parametrize``
being the recommended alternative.

View File

@ -377,7 +377,7 @@ class TestGeneralUsage:
res = testdir.runpytest(p)
res.stdout.fnmatch_lines([
"*source code not available*",
"*fixture 'invalid_fixture' not found",
"E*fixture 'invalid_fixture' not found",
])
def test_plugins_given_as_strings(self, tmpdir, monkeypatch):

View File

@ -121,6 +121,18 @@ class TestClass:
colitems = modcol.collect()
assert len(colitems) == 0
def test_issue1579_namedtuple(self, testdir):
testdir.makepyfile("""
import collections
TestCase = collections.namedtuple('TestCase', ['a'])
""")
result = testdir.runpytest('-rw')
result.stdout.fnmatch_lines(
"*cannot collect test class 'TestCase' "
"because it has a __new__ constructor*"
)
class TestGenerator:
def test_generative_functions(self, testdir):

View File

@ -351,6 +351,38 @@ class TestFillFixtures:
result = testdir.runpytest(testfile)
result.stdout.fnmatch_lines(["*3 passed*"])
def test_override_autouse_fixture_with_parametrized_fixture_conftest_conftest(self, testdir):
"""Test override of the autouse fixture with parametrized one on the conftest level.
This test covers the issue explained in issue 1601
"""
testdir.makeconftest("""
import pytest
@pytest.fixture(autouse=True)
def spam():
return 'spam'
""")
subdir = testdir.mkpydir('subdir')
subdir.join("conftest.py").write(_pytest._code.Source("""
import pytest
@pytest.fixture(params=[1, 2, 3])
def spam(request):
return request.param
"""))
testfile = subdir.join("test_spam.py")
testfile.write(_pytest._code.Source("""
params = {'spam': 1}
def test_spam(spam):
assert spam == params['spam']
params['spam'] += 1
"""))
result = testdir.runpytest()
result.stdout.fnmatch_lines(["*3 passed*"])
result = testdir.runpytest(testfile)
result.stdout.fnmatch_lines(["*3 passed*"])
def test_autouse_fixture_plugin(self, testdir):
# A fixture from a plugin has no baseid set, which screwed up
# the autouse fixture handling.

View File

@ -930,6 +930,43 @@ class TestMetafuncFunctional:
reprec = testdir.inline_run()
reprec.assertoutcome(passed=5)
def test_parametrize_issue634(self, testdir):
testdir.makepyfile('''
import pytest
@pytest.fixture(scope='module')
def foo(request):
print('preparing foo-%d' % request.param)
return 'foo-%d' % request.param
def test_one(foo):
pass
def test_two(foo):
pass
test_two.test_with = (2, 3)
def pytest_generate_tests(metafunc):
params = (1, 2, 3, 4)
if not 'foo' in metafunc.fixturenames:
return
test_with = getattr(metafunc.function, 'test_with', None)
if test_with:
params = test_with
metafunc.parametrize('foo', params, indirect=True)
''')
result = testdir.runpytest("-s")
output = result.stdout.str()
assert output.count('preparing foo-2') == 1
assert output.count('preparing foo-3') == 1
def test_parametrize_issue323(self, testdir):
testdir.makepyfile("""
import pytest

View File

@ -416,9 +416,9 @@ class TestCaptureFixture:
result = testdir.runpytest(p)
result.stdout.fnmatch_lines([
"*ERROR*setup*test_one*",
"*capsys*capfd*same*time*",
"E*capsys*capfd*same*time*",
"*ERROR*setup*test_two*",
"*capsys*capfd*same*time*",
"E*capsys*capfd*same*time*",
"*2 error*"])
def test_capturing_getfixturevalue(self, testdir):

View File

@ -448,6 +448,18 @@ def test_pytest_fail():
s = excinfo.exconly(tryshort=True)
assert s.startswith("Failed")
def test_pytest_exit_msg(testdir):
testdir.makeconftest("""
import pytest
def pytest_configure(config):
pytest.exit('oh noes')
""")
result = testdir.runpytest()
result.stderr.fnmatch_lines([
"Exit: oh noes",
])
def test_pytest_fail_notrace(testdir):
testdir.makepyfile("""
import pytest