Merge pull request #4524 from blueyed/merge-master
Merge master into features
This commit is contained in:
commit
038f1f94c2
|
@ -0,0 +1 @@
|
|||
Document common doctest fixture directory tree structure pitfalls
|
|
@ -0,0 +1 @@
|
|||
Validate arguments from the ``PYTEST_ADDOPTS`` environment variable and the ``addopts`` ini option separately.
|
|
@ -0,0 +1 @@
|
|||
When a fixture yields and a log call is made after the test runs, and, if the test is interrupted, capture attributes are ``None``.
|
|
@ -154,6 +154,9 @@ which can then be used in your doctests directly::
|
|||
"""
|
||||
pass
|
||||
|
||||
Note that like the normal ``conftest.py``, the fixtures are discovered in the directory tree conftest is in.
|
||||
Meaning that if you put your doctest with your source code, the relevant conftest.py needs to be in the same directory tree.
|
||||
Fixtures will not be discovered in a sibling directory tree!
|
||||
|
||||
Output format
|
||||
-------------
|
||||
|
|
|
@ -156,4 +156,4 @@ More details can be found in the `original PR <https://github.com/pytest-dev/pyt
|
|||
.. note::
|
||||
|
||||
in a future major relase of pytest we will introduce class based markers,
|
||||
at which points markers will no longer be limited to instances of :py:class:`Mark`
|
||||
at which point markers will no longer be limited to instances of :py:class:`Mark`
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
pygments-pytest>=1.0.4
|
||||
# pinning sphinx to 1.4.* due to search issues with rtd:
|
||||
# https://github.com/rtfd/readthedocs-sphinx-ext/issues/25
|
||||
sphinx ==1.4.*
|
||||
pygments-pytest>=1.1.0
|
||||
sphinx>=1.8.2
|
||||
sphinxcontrib-trio
|
||||
|
|
|
@ -117,7 +117,10 @@ class CaptureManager(object):
|
|||
self._global_capturing = None
|
||||
|
||||
def resume_global_capture(self):
|
||||
self._global_capturing.resume_capturing()
|
||||
# During teardown of the python process, and on rare occasions, capture
|
||||
# attributes can be `None` while trying to resume global capture.
|
||||
if self._global_capturing is not None:
|
||||
self._global_capturing.resume_capturing()
|
||||
|
||||
def suspend_global_capture(self, in_=False):
|
||||
cap = getattr(self, "_global_capturing", None)
|
||||
|
|
|
@ -777,12 +777,21 @@ class Config(object):
|
|||
for name in _iter_rewritable_modules(package_files):
|
||||
hook.mark_rewrite(name)
|
||||
|
||||
def _validate_args(self, args):
|
||||
"""Validate known args."""
|
||||
self._parser.parse_known_and_unknown_args(
|
||||
args, namespace=copy.copy(self.option)
|
||||
)
|
||||
return args
|
||||
|
||||
def _preparse(self, args, addopts=True):
|
||||
if addopts:
|
||||
args[:] = shlex.split(os.environ.get("PYTEST_ADDOPTS", "")) + args
|
||||
env_addopts = os.environ.get("PYTEST_ADDOPTS", "")
|
||||
if len(env_addopts):
|
||||
args[:] = self._validate_args(shlex.split(env_addopts)) + args
|
||||
self._initini(args)
|
||||
if addopts:
|
||||
args[:] = self.getini("addopts") + args
|
||||
args[:] = self._validate_args(self.getini("addopts")) + args
|
||||
self._checkversion()
|
||||
self._consider_importhook(args)
|
||||
self.pluginmanager.consider_preparse(args)
|
||||
|
|
|
@ -197,7 +197,8 @@ class TestRaises(object):
|
|||
pass
|
||||
|
||||
with pytest.raises(
|
||||
Failed, match="DID NOT RAISE <class 'raises.ClassLooksIterableException'>"
|
||||
Failed,
|
||||
match=r"DID NOT RAISE <class 'raises(\..*)*ClassLooksIterableException'>",
|
||||
):
|
||||
pytest.raises(ClassLooksIterableException, lambda: None)
|
||||
|
||||
|
|
|
@ -302,14 +302,14 @@ class TestLoggingInteraction(object):
|
|||
"""\
|
||||
import logging
|
||||
def setup_function(function):
|
||||
logging.warn("hello1")
|
||||
logging.warning("hello1")
|
||||
|
||||
def test_logging():
|
||||
logging.warn("hello2")
|
||||
logging.warning("hello2")
|
||||
assert 0
|
||||
|
||||
def teardown_function(function):
|
||||
logging.warn("hello3")
|
||||
logging.warning("hello3")
|
||||
assert 0
|
||||
"""
|
||||
)
|
||||
|
@ -328,14 +328,14 @@ class TestLoggingInteraction(object):
|
|||
"""\
|
||||
import logging
|
||||
def setup_module(function):
|
||||
logging.warn("hello1")
|
||||
logging.warning("hello1")
|
||||
|
||||
def test_logging():
|
||||
logging.warn("hello2")
|
||||
logging.warning("hello2")
|
||||
assert 0
|
||||
|
||||
def teardown_module(function):
|
||||
logging.warn("hello3")
|
||||
logging.warning("hello3")
|
||||
assert 0
|
||||
"""
|
||||
)
|
||||
|
@ -354,7 +354,7 @@ class TestLoggingInteraction(object):
|
|||
"""\
|
||||
import logging
|
||||
logging.basicConfig()
|
||||
logging.warn("hello435")
|
||||
logging.warning("hello435")
|
||||
"""
|
||||
)
|
||||
# make sure that logging is still captured in tests
|
||||
|
@ -375,7 +375,7 @@ class TestLoggingInteraction(object):
|
|||
"""\
|
||||
def test_hello():
|
||||
import logging
|
||||
logging.warn("hello433")
|
||||
logging.warning("hello433")
|
||||
assert 0
|
||||
"""
|
||||
)
|
||||
|
@ -385,6 +385,40 @@ class TestLoggingInteraction(object):
|
|||
assert "something" not in result.stderr.str()
|
||||
assert "operation on closed file" not in result.stderr.str()
|
||||
|
||||
def test_logging_after_cap_stopped(self, testdir):
|
||||
testdir.makeconftest(
|
||||
"""\
|
||||
import pytest
|
||||
import logging
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@pytest.fixture
|
||||
def log_on_teardown():
|
||||
yield
|
||||
log.warning('Logging on teardown')
|
||||
"""
|
||||
)
|
||||
# make sure that logging is still captured in tests
|
||||
p = testdir.makepyfile(
|
||||
"""\
|
||||
def test_hello(log_on_teardown):
|
||||
import logging
|
||||
logging.warning("hello433")
|
||||
assert 1
|
||||
raise KeyboardInterrupt()
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest_subprocess(p, "--log-cli-level", "info")
|
||||
assert result.ret != 0
|
||||
result.stdout.fnmatch_lines(
|
||||
["*WARNING*hello433*", "*WARNING*Logging on teardown*"]
|
||||
)
|
||||
assert (
|
||||
"AttributeError: 'NoneType' object has no attribute 'resume_capturing'"
|
||||
not in result.stderr.str()
|
||||
)
|
||||
|
||||
|
||||
class TestCaptureFixture(object):
|
||||
@pytest.mark.parametrize("opt", [[], ["-s"]])
|
||||
|
@ -1300,13 +1334,13 @@ def test_capturing_and_logging_fundamentals(testdir, method):
|
|||
Capture=capture.%s)
|
||||
cap.start_capturing()
|
||||
|
||||
logging.warn("hello1")
|
||||
logging.warning("hello1")
|
||||
outerr = cap.readouterr()
|
||||
print("suspend, captured %%s" %%(outerr,))
|
||||
logging.warn("hello2")
|
||||
logging.warning("hello2")
|
||||
|
||||
cap.pop_outerr_to_orig()
|
||||
logging.warn("hello3")
|
||||
logging.warning("hello3")
|
||||
|
||||
outerr = cap.readouterr()
|
||||
print("suspend2, captured %%s" %% (outerr,))
|
||||
|
|
|
@ -1083,6 +1083,33 @@ class TestOverrideIniArgs(object):
|
|||
config._preparse([], addopts=True)
|
||||
assert config._override_ini == ["cache_dir=%s" % cache_dir]
|
||||
|
||||
def test_addopts_from_env_not_concatenated(self, monkeypatch):
|
||||
"""PYTEST_ADDOPTS should not take values from normal args (#4265)."""
|
||||
from _pytest.config import get_config
|
||||
|
||||
monkeypatch.setenv("PYTEST_ADDOPTS", "-o")
|
||||
config = get_config()
|
||||
with pytest.raises(SystemExit) as excinfo:
|
||||
config._preparse(["cache_dir=ignored"], addopts=True)
|
||||
assert excinfo.value.args[0] == _pytest.main.EXIT_USAGEERROR
|
||||
|
||||
def test_addopts_from_ini_not_concatenated(self, testdir):
|
||||
"""addopts from ini should not take values from normal args (#4265)."""
|
||||
testdir.makeini(
|
||||
"""
|
||||
[pytest]
|
||||
addopts=-o
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest("cache_dir=ignored")
|
||||
result.stderr.fnmatch_lines(
|
||||
[
|
||||
"%s: error: argument -o/--override-ini: expected one argument"
|
||||
% (testdir.request.config._parser.optparser.prog,)
|
||||
]
|
||||
)
|
||||
assert result.ret == _pytest.main.EXIT_USAGEERROR
|
||||
|
||||
def test_override_ini_does_not_contain_paths(self):
|
||||
"""Check that -o no longer swallows all options after it (#3103)"""
|
||||
from _pytest.config import get_config
|
||||
|
|
Loading…
Reference in New Issue