Merge master into features
This commit is contained in:
		
						commit
						0db5ccb0dd
					
				|  | @ -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,6 +117,9 @@ class CaptureManager(object): | |||
|             self._global_capturing = None | ||||
| 
 | ||||
|     def resume_global_capture(self): | ||||
|         # 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): | ||||
|  |  | |||
|  | @ -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) | ||||
|  |  | |||
|  | @ -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