Merge pull request #3269 from nicoddemus/merge-master-into-features

Merge master into features
This commit is contained in:
Bruno Oliveira 2018-02-27 22:42:08 -03:00 committed by GitHub
commit 0a5a6c19be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 92 additions and 14 deletions

View File

@ -202,3 +202,4 @@ Xuan Luong
Xuecong Liao
Zoltán Máté
Roland Puntaier
Allan Feldman

View File

@ -23,6 +23,9 @@
.. image:: https://ci.appveyor.com/api/projects/status/mrgbjaua7t33pg6b?svg=true
:target: https://ci.appveyor.com/project/pytestbot/pytest
.. image:: https://www.codetriage.com/pytest-dev/pytest/badges/users.svg
:target: https://www.codetriage.com/pytest-dev/pytest
The ``pytest`` framework makes it easy to write small tests, yet
scales to support complex functional testing for applications and libraries.

View File

@ -1328,10 +1328,14 @@ def determine_setup(inifile, args, warnfunc=None, rootdir_cmd_arg=None):
dirs = get_dirs_from_args(args)
if inifile:
iniconfig = py.iniconfig.IniConfig(inifile)
try:
inicfg = iniconfig["pytest"]
except KeyError:
inicfg = None
is_cfg_file = str(inifile).endswith('.cfg')
sections = ['tool:pytest', 'pytest'] if is_cfg_file else ['pytest']
for section in sections:
try:
inicfg = iniconfig[section]
break
except KeyError:
inicfg = None
rootdir = get_common_ancestor(dirs)
else:
ancestor = get_common_ancestor(dirs)

View File

@ -24,6 +24,12 @@ from _pytest.compat import (
from _pytest.outcomes import fail, TEST_OUTCOME
@attr.s(frozen=True)
class PseudoFixtureDef(object):
cached_result = attr.ib()
scope = attr.ib()
def pytest_sessionstart(session):
import _pytest.python
import _pytest.nodes
@ -440,10 +446,9 @@ class FixtureRequest(FuncargnamesCompatAttr):
fixturedef = self._getnextfixturedef(argname)
except FixtureLookupError:
if argname == "request":
class PseudoFixtureDef(object):
cached_result = (self, [0], None)
scope = "function"
return PseudoFixtureDef
cached_result = (self, [0], None)
scope = "function"
return PseudoFixtureDef(cached_result, scope)
raise
# remove indent to prevent the python3 exception
# from leaking into the call

View File

@ -153,6 +153,8 @@ class ApproxScalar(ApproxBase):
"""
Perform approximate comparisons for single numbers only.
"""
DEFAULT_ABSOLUTE_TOLERANCE = 1e-12
DEFAULT_RELATIVE_TOLERANCE = 1e-6
def __repr__(self):
"""
@ -223,7 +225,7 @@ class ApproxScalar(ApproxBase):
# Figure out what the absolute tolerance should be. ``self.abs`` is
# either None or a value specified by the user.
absolute_tolerance = set_default(self.abs, 1e-12)
absolute_tolerance = set_default(self.abs, self.DEFAULT_ABSOLUTE_TOLERANCE)
if absolute_tolerance < 0:
raise ValueError("absolute tolerance can't be negative: {}".format(absolute_tolerance))
@ -241,7 +243,7 @@ class ApproxScalar(ApproxBase):
# we've made sure the user didn't ask for an absolute tolerance only,
# because we don't want to raise errors about the relative tolerance if
# we aren't even going to use it.
relative_tolerance = set_default(self.rel, 1e-6) * abs(self.expected)
relative_tolerance = set_default(self.rel, self.DEFAULT_RELATIVE_TOLERANCE) * abs(self.expected)
if relative_tolerance < 0:
raise ValueError("relative tolerance can't be negative: {}".format(absolute_tolerance))
@ -252,6 +254,13 @@ class ApproxScalar(ApproxBase):
return max(relative_tolerance, absolute_tolerance)
class ApproxDecimal(ApproxScalar):
from decimal import Decimal
DEFAULT_ABSOLUTE_TOLERANCE = Decimal('1e-12')
DEFAULT_RELATIVE_TOLERANCE = Decimal('1e-6')
def approx(expected, rel=None, abs=None, nan_ok=False):
"""
Assert that two numbers (or two sets of numbers) are equal to each other
@ -401,6 +410,7 @@ def approx(expected, rel=None, abs=None, nan_ok=False):
from collections import Mapping, Sequence
from _pytest.compat import STRING_TYPES as String
from decimal import Decimal
# Delegate the comparison to a class that knows how to deal with the type
# of the expected value (e.g. int, float, list, dict, numpy.array, etc).
@ -422,6 +432,8 @@ def approx(expected, rel=None, abs=None, nan_ok=False):
cls = ApproxMapping
elif isinstance(expected, Sequence) and not isinstance(expected, String):
cls = ApproxSequence
elif isinstance(expected, Decimal):
cls = ApproxDecimal
else:
cls = ApproxScalar

View File

@ -329,6 +329,8 @@ class TerminalReporter(object):
_PROGRESS_LENGTH = len(' [100%]')
def _get_progress_information_message(self):
if self.config.getoption('capture') == 'no':
return ''
collected = self._session.testscollected
if collected:
progress = len(self._progress_nodeids_reported) * 100 // collected

View File

@ -0,0 +1 @@
Removed progress information when capture option is ``no``.

View File

@ -0,0 +1 @@
Fix ``TypeError`` issue when using ``approx`` with a ``Decimal`` value.

View File

@ -0,0 +1 @@
Fix reference cycle generated when using the ``request`` fixture.

1
changelog/3259.trivial Normal file
View File

@ -0,0 +1 @@
Fix minor typo in fixture.rst

View File

@ -0,0 +1 @@
``[tool:pytest]`` sections in ``*.cfg`` files passed by the ``-c`` option are now properly recognized.

View File

@ -369,7 +369,7 @@ ends, but ``addfinalizer`` has two key differences over ``yield``:
Fixtures can introspect the requesting test context
-------------------------------------------------------------
Fixture function can accept the :py:class:`request <FixtureRequest>` object
Fixture functions can accept the :py:class:`request <FixtureRequest>` object
to introspect the "requesting" test function, class or module context.
Further extending the previous ``smtp`` fixture example, let's
read an optional server URL from the test module which uses our fixture::

View File

@ -160,9 +160,9 @@ List the name ``tmpdir`` in the test function signature and ``pytest`` will look
PYTEST_TMPDIR/test_needsfiles0
1 failed in 0.12 seconds
More info on tmpdir handling is available at `Temporary directories and files <tmpdir handling>`_.
More info on tmpdir handling is available at :ref:`Temporary directories and files <tmpdir handling>`.
Find out what kind of builtin ```pytest`` fixtures <fixtures>`_ exist with the command::
Find out what kind of builtin :ref:`pytest fixtures <fixtures>` exist with the command::
pytest --fixtures # shows builtin and custom fixtures

View File

@ -278,7 +278,7 @@ the plugin manager like this:
.. sourcecode:: python
plugin = config.pluginmanager.getplugin("name_of_plugin")
plugin = config.pluginmanager.get_plugin("name_of_plugin")
If you want to look at the names of existing plugins, use
the ``--trace-config`` option.

View File

@ -249,6 +249,7 @@ class TestApprox(object):
(Decimal('-1.000001'), Decimal('-1.0')),
]
for a, x in within_1e6:
assert a == approx(x)
assert a == approx(x, rel=Decimal('5e-6'), abs=0)
assert a != approx(x, rel=Decimal('5e-7'), abs=0)
assert approx(x, rel=Decimal('5e-6'), abs=0) == a

View File

@ -519,6 +519,41 @@ class TestRequestBasic(object):
assert len(arg2fixturedefs) == 1
assert arg2fixturedefs['something'][0].argname == "something"
def test_request_garbage(self, testdir):
testdir.makepyfile("""
import sys
import pytest
import gc
@pytest.fixture(autouse=True)
def something(request):
# this method of test doesn't work on pypy
if hasattr(sys, "pypy_version_info"):
yield
else:
original = gc.get_debug()
gc.set_debug(gc.DEBUG_SAVEALL)
gc.collect()
yield
gc.collect()
leaked_types = sum(1 for _ in gc.garbage
if 'PseudoFixtureDef' in str(_))
gc.garbage[:] = []
try:
assert leaked_types == 0
finally:
gc.set_debug(original)
def test_func():
pass
""")
reprec = testdir.inline_run()
reprec.assertoutcome(passed=1)
def test_getfixturevalue_recursive(self, testdir):
testdir.makeconftest("""
import pytest

View File

@ -110,6 +110,13 @@ class TestConfigCmdlineParsing(object):
config = testdir.parseconfig("-c", "custom.cfg")
assert config.getini("custom") == "1"
testdir.makefile(".cfg", custom_tool_pytest_section="""
[tool:pytest]
custom = 1
""")
config = testdir.parseconfig("-c", "custom_tool_pytest_section.cfg")
assert config.getini("custom") == "1"
def test_absolute_win32_path(self, testdir):
temp_cfg_file = testdir.makefile(".cfg", custom="""
[pytest]

View File

@ -1121,6 +1121,9 @@ class TestProgress(object):
r'test_foobar.py \.{5}',
])
output = testdir.runpytest('--capture=no')
assert "%]" not in output.stdout.str()
class TestProgressWithTeardown(object):
"""Ensure we show the correct percentages for tests that fail during teardown (#3088)"""