Merge branch 'master' of github.com:pytest-dev/pytest

This commit is contained in:
Rachel Kogan 2018-04-17 16:21:04 -04:00
commit 8ff8a82c51
14 changed files with 81 additions and 39 deletions

View File

@ -48,8 +48,7 @@ fix the bug itself.
Fix bugs Fix bugs
-------- --------
Look through the GitHub issues for bugs. Here is a filter you can use: Look through the `GitHub issues for bugs <https://github.com/pytest-dev/pytest/labels/type:%20bug>`_.
https://github.com/pytest-dev/pytest/labels/type%3A%20bug
:ref:`Talk <contact>` to developers to find out how you can fix specific bugs. :ref:`Talk <contact>` to developers to find out how you can fix specific bugs.
@ -60,8 +59,7 @@ Don't forget to check the issue trackers of your favourite plugins, too!
Implement features Implement features
------------------ ------------------
Look through the GitHub issues for enhancements. Here is a filter you can use: Look through the `GitHub issues for enhancements <https://github.com/pytest-dev/pytest/labels/type:%20enhancement>`_.
https://github.com/pytest-dev/pytest/labels/enhancement
:ref:`Talk <contact>` to developers to find out how you can implement specific :ref:`Talk <contact>` to developers to find out how you can implement specific
features. features.

View File

@ -138,7 +138,8 @@ def showhelp(config):
tw.line("to see available markers type: pytest --markers") tw.line("to see available markers type: pytest --markers")
tw.line("to see available fixtures type: pytest --fixtures") tw.line("to see available fixtures type: pytest --fixtures")
tw.line("(shown according to specified file_or_dir or current dir " tw.line("(shown according to specified file_or_dir or current dir "
"if not specified)") "if not specified; fixtures with leading '_' are only shown "
"with the '-v' option")
for warningreport in reporter.stats.get('warnings', []): for warningreport in reporter.stats.get('warnings', []):
tw.line("warning : " + warningreport.message, red=True) tw.line("warning : " + warningreport.message, red=True)

View File

@ -75,7 +75,8 @@ def pytest_addoption(parser):
group = parser.getgroup("general") group = parser.getgroup("general")
group.addoption('--fixtures', '--funcargs', group.addoption('--fixtures', '--funcargs',
action="store_true", dest="showfixtures", default=False, action="store_true", dest="showfixtures", default=False,
help="show available fixtures, sorted by plugin appearance") help="show available fixtures, sorted by plugin appearance "
"(fixtures with leading '_' are only shown with '-v')")
group.addoption( group.addoption(
'--fixtures-per-test', '--fixtures-per-test',
action="store_true", action="store_true",

View File

@ -105,6 +105,7 @@ def pytest_runtest_setup(item):
def pytest_runtest_call(item): def pytest_runtest_call(item):
_update_current_test_var(item, 'call') _update_current_test_var(item, 'call')
sys.last_type, sys.last_value, sys.last_traceback = (None, None, None)
try: try:
item.runtest() item.runtest()
except Exception: except Exception:
@ -114,7 +115,7 @@ def pytest_runtest_call(item):
sys.last_type = type sys.last_type = type
sys.last_value = value sys.last_value = value
sys.last_traceback = tb sys.last_traceback = tb
del tb # Get rid of it in this namespace del type, value, tb # Get rid of these in this frame
raise raise

View File

@ -0,0 +1,3 @@
Reset ``sys.last_type``, ``sys.last_value`` and ``sys.last_traceback`` before each test executes. Those attributes
are added by pytest during the test run to aid debugging, but were never reset so they would create a leaking
reference to the last failing test's frame which in turn could never be reclaimed by the garbage collector.

View File

@ -0,0 +1 @@
Mention in documentation and CLI help that fixtures with leading ``_`` are printed by ``pytest --fixtures`` only if the ``-v`` option is added.

View File

@ -12,7 +12,7 @@ For information on plugin hooks and objects, see :ref:`plugins`.
For information on the ``pytest.mark`` mechanism, see :ref:`mark`. For information on the ``pytest.mark`` mechanism, see :ref:`mark`.
For information about fixtures, see :ref:`fixtures`. To see a complete list of available fixtures, type:: For information about fixtures, see :ref:`fixtures`. To see a complete list of available fixtures (add ``-v`` to also see fixtures with leading ``_``), type ::
$ pytest -q --fixtures $ pytest -q --fixtures
cache cache

View File

@ -115,7 +115,7 @@ with a list of available function arguments.
pytest --fixtures test_simplefactory.py pytest --fixtures test_simplefactory.py
to see available fixtures. to see available fixtures (fixtures with leading ``_`` are only shown if you add the ``-v`` option).
Fixtures: a prime example of dependency injection Fixtures: a prime example of dependency injection
--------------------------------------------------- ---------------------------------------------------

View File

@ -166,6 +166,8 @@ Find out what kind of builtin :ref:`pytest fixtures <fixtures>` exist with the c
pytest --fixtures # shows builtin and custom fixtures pytest --fixtures # shows builtin and custom fixtures
Note that this command omits fixtures with leading ``_`` unless the ``-v`` option is added.
Continue reading Continue reading
------------------------------------- -------------------------------------

View File

@ -23,7 +23,7 @@ command line options
``--full-trace`` ``--full-trace``
don't cut any tracebacks (default is to cut). don't cut any tracebacks (default is to cut).
``--fixtures`` ``--fixtures``
show available function arguments, sorted by plugin show available fixtures, sorted by plugin appearance (fixtures with leading ``_`` are only shown with '-v')
Start improving this plugin in 30 seconds Start improving this plugin in 30 seconds
========================================= =========================================

View File

@ -87,6 +87,10 @@ def main():
'write_to': '_pytest/_version.py', 'write_to': '_pytest/_version.py',
}, },
url='http://pytest.org', url='http://pytest.org',
project_urls={
'Source': 'https://github.com/pytest-dev/pytest',
'Tracker': 'https://github.com/pytest-dev/pytest/issues',
},
license='MIT license', license='MIT license',
platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'], platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],
author=( author=(

View File

@ -988,3 +988,33 @@ def test_fixture_order_respects_scope(testdir):
''') ''')
result = testdir.runpytest() result = testdir.runpytest()
assert result.ret == 0 assert result.ret == 0
def test_frame_leak_on_failing_test(testdir):
"""pytest would leak garbage referencing the frames of tests that failed that could never be reclaimed (#2798)
Unfortunately it was not possible to remove the actual circles because most of them
are made of traceback objects which cannot be weakly referenced. Those objects at least
can be eventually claimed by the garbage collector.
"""
testdir.makepyfile('''
import gc
import weakref
class Obj:
pass
ref = None
def test1():
obj = Obj()
global ref
ref = weakref.ref(obj)
assert 0
def test2():
gc.collect()
assert ref() is None
''')
result = testdir.runpytest_subprocess()
result.stdout.fnmatch_lines(['*1 failed, 1 passed in*'])

View File

@ -719,18 +719,20 @@ def test_makereport_getsource_dynamic_code(testdir, monkeypatch):
result.stdout.fnmatch_lines(["*test_fix*", "*fixture*'missing'*not found*"]) result.stdout.fnmatch_lines(["*test_fix*", "*fixture*'missing'*not found*"])
def test_store_except_info_on_eror(): def test_store_except_info_on_error():
""" Test that upon test failure, the exception info is stored on """ Test that upon test failure, the exception info is stored on
sys.last_traceback and friends. sys.last_traceback and friends.
""" """
# Simulate item that raises a specific exception # Simulate item that might raise a specific exception, depending on `raise_error` class var
class ItemThatRaises(object): class ItemMightRaise(object):
nodeid = 'item_that_raises' nodeid = 'item_that_raises'
raise_error = True
def runtest(self): def runtest(self):
if self.raise_error:
raise IndexError('TEST') raise IndexError('TEST')
try: try:
runner.pytest_runtest_call(ItemThatRaises()) runner.pytest_runtest_call(ItemMightRaise())
except IndexError: except IndexError:
pass pass
# Check that exception info is stored on sys # Check that exception info is stored on sys
@ -738,6 +740,13 @@ def test_store_except_info_on_eror():
assert sys.last_value.args[0] == 'TEST' assert sys.last_value.args[0] == 'TEST'
assert sys.last_traceback assert sys.last_traceback
# The next run should clear the exception info stored by the previous run
ItemMightRaise.raise_error = False
runner.pytest_runtest_call(ItemMightRaise())
assert sys.last_type is None
assert sys.last_value is None
assert sys.last_traceback is None
def test_current_test_env_var(testdir, monkeypatch): def test_current_test_env_var(testdir, monkeypatch):
pytest_current_test_vars = [] pytest_current_test_vars = []

34
tox.ini
View File

@ -13,7 +13,7 @@ envlist =
{py27,py36}-{pexpect,xdist,trial,numpy,pluggymaster} {py27,py36}-{pexpect,xdist,trial,numpy,pluggymaster}
py27-nobyte py27-nobyte
doctesting doctesting
py35-freeze py36-freeze
docs docs
[testenv] [testenv]
@ -56,12 +56,11 @@ deps =
hypothesis>=3.5.2 hypothesis>=3.5.2
changedir=testing changedir=testing
commands = commands =
pytest -n1 -ra {posargs:.} pytest -n8 -ra {posargs:.}
[testenv:py36-xdist] [testenv:py36-xdist]
deps = {[testenv:py27-xdist]deps} deps = {[testenv:py27-xdist]deps}
commands = commands = {[testenv:py27-xdist]commands}
pytest -n3 -ra {posargs:testing}
[testenv:py27-pexpect] [testenv:py27-pexpect]
changedir = testing changedir = testing
@ -71,11 +70,10 @@ commands =
pytest -ra test_pdb.py test_terminal.py test_unittest.py pytest -ra test_pdb.py test_terminal.py test_unittest.py
[testenv:py36-pexpect] [testenv:py36-pexpect]
changedir = testing changedir = {[testenv:py27-pexpect]changedir}
platform = linux|darwin platform = {[testenv:py27-pexpect]platform}
deps = {[testenv:py27-pexpect]deps} deps = {[testenv:py27-pexpect]deps}
commands = commands = {[testenv:py27-pexpect]commands}
pytest -ra test_pdb.py test_terminal.py test_unittest.py
[testenv:py27-nobyte] [testenv:py27-nobyte]
deps = deps =
@ -95,8 +93,7 @@ commands =
[testenv:py36-trial] [testenv:py36-trial]
deps = {[testenv:py27-trial]deps} deps = {[testenv:py27-trial]deps}
commands = commands = {[testenv:py27-trial]commands}
pytest -ra {posargs:testing/test_unittest.py}
[testenv:py27-numpy] [testenv:py27-numpy]
deps = numpy deps = numpy
@ -104,9 +101,8 @@ commands=
pytest -ra {posargs:testing/python/approx.py} pytest -ra {posargs:testing/python/approx.py}
[testenv:py36-numpy] [testenv:py36-numpy]
deps=numpy deps = {[testenv:py27-numpy]deps}
commands= commands = {[testenv:py27-numpy]commands}
pytest -ra {posargs:testing/python/approx.py}
[testenv:py27-pluggymaster] [testenv:py27-pluggymaster]
setenv= setenv=
@ -115,12 +111,9 @@ deps =
{[testenv]deps} {[testenv]deps}
git+https://github.com/pytest-dev/pluggy.git@master git+https://github.com/pytest-dev/pluggy.git@master
[testenv:py35-pluggymaster] [testenv:py36-pluggymaster]
setenv= setenv = {[testenv:py27-pluggymaster]setenv}
_PYTEST_SETUP_SKIP_PLUGGY_DEP=1 deps = {[testenv:py27-pluggymaster]deps}
deps =
{[testenv:py27-pluggymaster]deps}
git+https://github.com/pytest-dev/pluggy.git@master
[testenv:docs] [testenv:docs]
skipsdist = True skipsdist = True
@ -176,7 +169,7 @@ changedir = testing
commands = commands =
{envpython} {envbindir}/py.test-jython -ra {posargs} {envpython} {envbindir}/py.test-jython -ra {posargs}
[testenv:py35-freeze] [testenv:py36-freeze]
changedir = testing/freeze changedir = testing/freeze
deps = pyinstaller deps = pyinstaller
commands = commands =
@ -199,7 +192,6 @@ commands =
[pytest] [pytest]
minversion = 2.0 minversion = 2.0
plugins = pytester plugins = pytester
#--pyargs --doctest-modules --ignore=.tox
addopts = -ra -p pytester --ignore=testing/cx_freeze addopts = -ra -p pytester --ignore=testing/cx_freeze
rsyncdirs = tox.ini pytest.py _pytest testing rsyncdirs = tox.ini pytest.py _pytest testing
python_files = test_*.py *_test.py testing/*/*.py python_files = test_*.py *_test.py testing/*/*.py