Merge remote-tracking branch 'upstream/master' into merge-master-into-features
This commit is contained in:
		
						commit
						1101a20408
					
				
							
								
								
									
										6
									
								
								AUTHORS
								
								
								
								
							
							
						
						
									
										6
									
								
								AUTHORS
								
								
								
								
							|  | @ -10,6 +10,7 @@ Ahn Ki-Wook | ||||||
| Alan Velasco | Alan Velasco | ||||||
| Alexander Johnson | Alexander Johnson | ||||||
| Alexei Kozlenok | Alexei Kozlenok | ||||||
|  | Allan Feldman | ||||||
| Anatoly Bubenkoff | Anatoly Bubenkoff | ||||||
| Anders Hovmöller | Anders Hovmöller | ||||||
| Andras Tim | Andras Tim | ||||||
|  | @ -94,6 +95,7 @@ Hui Wang (coldnight) | ||||||
| Ian Bicking | Ian Bicking | ||||||
| Ian Lesperance | Ian Lesperance | ||||||
| Ionuț Turturică | Ionuț Turturică | ||||||
|  | Iwan Briquemont | ||||||
| Jaap Broekhuizen | Jaap Broekhuizen | ||||||
| Jan Balster | Jan Balster | ||||||
| Janne Vanhala | Janne Vanhala | ||||||
|  | @ -179,6 +181,7 @@ Raphael Pierzina | ||||||
| Raquel Alegre | Raquel Alegre | ||||||
| Ravi Chandra | Ravi Chandra | ||||||
| Roberto Polli | Roberto Polli | ||||||
|  | Roland Puntaier | ||||||
| Romain Dorgueil | Romain Dorgueil | ||||||
| Roman Bolshakov | Roman Bolshakov | ||||||
| Ronny Pfannschmidt | Ronny Pfannschmidt | ||||||
|  | @ -223,6 +226,5 @@ Wim Glenn | ||||||
| Wouter van Ackooy | Wouter van Ackooy | ||||||
| Xuan Luong | Xuan Luong | ||||||
| Xuecong Liao | Xuecong Liao | ||||||
|  | Zac Hatfield-Dodds | ||||||
| Zoltán Máté | Zoltán Máté | ||||||
| Roland Puntaier |  | ||||||
| Allan Feldman |  | ||||||
|  |  | ||||||
|  | @ -18,6 +18,58 @@ with advance notice in the **Deprecations** section of releases. | ||||||
| 
 | 
 | ||||||
| .. towncrier release notes start | .. towncrier release notes start | ||||||
| 
 | 
 | ||||||
|  | pytest 3.8.2 (2018-10-02) | ||||||
|  | ========================= | ||||||
|  | 
 | ||||||
|  | Deprecations and Removals | ||||||
|  | ------------------------- | ||||||
|  | 
 | ||||||
|  | - `#4036 <https://github.com/pytest-dev/pytest/issues/4036>`_: The ``item`` parameter of ``pytest_warning_captured`` hook is now documented as deprecated. We realized only after | ||||||
|  |   the ``3.8`` release that this parameter is incompatible with ``pytest-xdist``. | ||||||
|  | 
 | ||||||
|  |   Our policy is to not deprecate features during bugfix releases, but in this case we believe it makes sense as we are | ||||||
|  |   only documenting it as deprecated, without issuing warnings which might potentially break test suites. This will get | ||||||
|  |   the word out that hook implementers should not use this parameter at all. | ||||||
|  | 
 | ||||||
|  |   In a future release ``item`` will always be ``None`` and will emit a proper warning when a hook implementation | ||||||
|  |   makes use of it. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | Bug Fixes | ||||||
|  | --------- | ||||||
|  | 
 | ||||||
|  | - `#3539 <https://github.com/pytest-dev/pytest/issues/3539>`_: Fix reload on assertion rewritten modules. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | - `#4034 <https://github.com/pytest-dev/pytest/issues/4034>`_: The ``.user_properties`` attribute of ``TestReport`` objects is a list | ||||||
|  |   of (name, value) tuples, but could sometimes be instantiated as a tuple | ||||||
|  |   of tuples.  It is now always a list. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | - `#4039 <https://github.com/pytest-dev/pytest/issues/4039>`_: No longer issue warnings about using ``pytest_plugins`` in non-top-level directories when using ``--pyargs``: the | ||||||
|  |   current ``--pyargs`` mechanism is not reliable and might give false negatives. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | - `#4040 <https://github.com/pytest-dev/pytest/issues/4040>`_: Exclude empty reports for passed tests when ``-rP`` option is used. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | - `#4051 <https://github.com/pytest-dev/pytest/issues/4051>`_: Improve error message when an invalid Python expression is passed to the ``-m`` option. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | - `#4056 <https://github.com/pytest-dev/pytest/issues/4056>`_: ``MonkeyPatch.setenv`` and ``MonkeyPatch.delenv`` issue a warning if the environment variable name is not ``str`` on Python 2. | ||||||
|  | 
 | ||||||
|  |   In Python 2, adding ``unicode`` keys to ``os.environ`` causes problems with ``subprocess`` (and possible other modules), | ||||||
|  |   making this a subtle bug specially susceptible when used with ``from __future__ import unicode_literals``. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | Improved Documentation | ||||||
|  | ---------------------- | ||||||
|  | 
 | ||||||
|  | - `#3928 <https://github.com/pytest-dev/pytest/issues/3928>`_: Add possible values for fixture scope to docs. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| pytest 3.8.1 (2018-09-22) | pytest 3.8.1 (2018-09-22) | ||||||
| ========================= | ========================= | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -6,6 +6,7 @@ Release announcements | ||||||
|    :maxdepth: 2 |    :maxdepth: 2 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |    release-3.8.2 | ||||||
|    release-3.8.1 |    release-3.8.1 | ||||||
|    release-3.8.0 |    release-3.8.0 | ||||||
|    release-3.7.4 |    release-3.7.4 | ||||||
|  |  | ||||||
|  | @ -0,0 +1,28 @@ | ||||||
|  | pytest-3.8.2 | ||||||
|  | ======================================= | ||||||
|  | 
 | ||||||
|  | pytest 3.8.2 has just been released to PyPI. | ||||||
|  | 
 | ||||||
|  | This is a bug-fix release, being a drop-in replacement. To upgrade:: | ||||||
|  | 
 | ||||||
|  |   pip install --upgrade pytest | ||||||
|  | 
 | ||||||
|  | The full changelog is available at https://docs.pytest.org/en/latest/changelog.html. | ||||||
|  | 
 | ||||||
|  | Thanks to all who contributed to this release, among them: | ||||||
|  | 
 | ||||||
|  | * Ankit Goel | ||||||
|  | * Anthony Sottile | ||||||
|  | * Bruno Oliveira | ||||||
|  | * Daniel Hahler | ||||||
|  | * Denis Otkidach | ||||||
|  | * Harry Percival | ||||||
|  | * Jeffrey Rackauckas | ||||||
|  | * Jose Carlos Menezes | ||||||
|  | * Ronny Pfannschmidt | ||||||
|  | * Zac-HD | ||||||
|  | * iwanb | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | Happy testing, | ||||||
|  | The pytest Development Team | ||||||
|  | @ -264,8 +264,12 @@ Advanced assertion introspection | ||||||
| Reporting details about a failing assertion is achieved by rewriting assert | Reporting details about a failing assertion is achieved by rewriting assert | ||||||
| statements before they are run.  Rewritten assert statements put introspection | statements before they are run.  Rewritten assert statements put introspection | ||||||
| information into the assertion failure message.  ``pytest`` only rewrites test | information into the assertion failure message.  ``pytest`` only rewrites test | ||||||
| modules directly discovered by its test collection process, so asserts in | modules directly discovered by its test collection process, so **asserts in | ||||||
| supporting modules which are not themselves test modules will not be rewritten. | supporting modules which are not themselves test modules will not be rewritten**. | ||||||
|  | 
 | ||||||
|  | You can manually enable assertion rewriting for an imported module by calling | ||||||
|  | `register_assert_rewrite <https://docs.pytest.org/en/latest/writing_plugins.html#assertion-rewriting>`_ | ||||||
|  | before you import it (a good place to do that is in ``conftest.py``). | ||||||
| 
 | 
 | ||||||
| .. note:: | .. note:: | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -83,14 +83,24 @@ message please contact the authors so they can change the code. | ||||||
| Those methods were part of the internal pytest warnings system, but since ``3.8`` pytest is using the builtin warning | Those methods were part of the internal pytest warnings system, but since ``3.8`` pytest is using the builtin warning | ||||||
| system for its own warnings, so those two functions are now deprecated. | system for its own warnings, so those two functions are now deprecated. | ||||||
| 
 | 
 | ||||||
| ``Config.warn`` should be replaced by calls to the standard ``warnings.warn``. | ``Config.warn`` should be replaced by calls to the standard ``warnings.warn``, example: | ||||||
|  | 
 | ||||||
|  | .. code-block:: python | ||||||
|  | 
 | ||||||
|  |     config.warn("C1", "some warning") | ||||||
|  | 
 | ||||||
|  | Becomes: | ||||||
|  | 
 | ||||||
|  | .. code-block:: python | ||||||
|  | 
 | ||||||
|  |     warnings.warn(pytest.PytestWarning("some warning")) | ||||||
| 
 | 
 | ||||||
| ``Node.warn`` now supports two signatures: | ``Node.warn`` now supports two signatures: | ||||||
| 
 | 
 | ||||||
| * ``node.warn(PytestWarning("some message"))``: is now the recommended way to call this function. | * ``node.warn(PytestWarning("some message"))``: is now the **recommended** way to call this function. | ||||||
|   The warning instance must be a PytestWarning or subclass. |   The warning instance must be a PytestWarning or subclass. | ||||||
| 
 | 
 | ||||||
| * ``node.warn("CI", "some message")``: this code/message form is now deprecated and should be converted to the warning instance form above. | * ``node.warn("CI", "some message")``: this code/message form is now **deprecated** and should be converted to the warning instance form above. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| ``pytest_namespace`` | ``pytest_namespace`` | ||||||
|  |  | ||||||
|  | @ -31,7 +31,7 @@ You can then restrict a test run to only run tests marked with ``webtest``:: | ||||||
| 
 | 
 | ||||||
|     $ pytest -v -m webtest |     $ pytest -v -m webtest | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 |     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python | ||||||
|     cachedir: .pytest_cache |     cachedir: .pytest_cache | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collecting ... collected 4 items / 3 deselected |     collecting ... collected 4 items / 3 deselected | ||||||
|  | @ -44,7 +44,7 @@ Or the inverse, running all tests except the webtest ones:: | ||||||
| 
 | 
 | ||||||
|     $ pytest -v -m "not webtest" |     $ pytest -v -m "not webtest" | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 |     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python | ||||||
|     cachedir: .pytest_cache |     cachedir: .pytest_cache | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collecting ... collected 4 items / 1 deselected |     collecting ... collected 4 items / 1 deselected | ||||||
|  | @ -64,7 +64,7 @@ tests based on their module, class, method, or function name:: | ||||||
| 
 | 
 | ||||||
|     $ pytest -v test_server.py::TestClass::test_method |     $ pytest -v test_server.py::TestClass::test_method | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 |     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python | ||||||
|     cachedir: .pytest_cache |     cachedir: .pytest_cache | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collecting ... collected 1 item |     collecting ... collected 1 item | ||||||
|  | @ -77,7 +77,7 @@ You can also select on the class:: | ||||||
| 
 | 
 | ||||||
|     $ pytest -v test_server.py::TestClass |     $ pytest -v test_server.py::TestClass | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 |     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python | ||||||
|     cachedir: .pytest_cache |     cachedir: .pytest_cache | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collecting ... collected 1 item |     collecting ... collected 1 item | ||||||
|  | @ -90,7 +90,7 @@ Or select multiple nodes:: | ||||||
| 
 | 
 | ||||||
|   $ pytest -v test_server.py::TestClass test_server.py::test_send_http |   $ pytest -v test_server.py::TestClass test_server.py::test_send_http | ||||||
|   =========================== test session starts ============================ |   =========================== test session starts ============================ | ||||||
|   platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 |   platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python | ||||||
|   cachedir: .pytest_cache |   cachedir: .pytest_cache | ||||||
|   rootdir: $REGENDOC_TMPDIR, inifile: |   rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|   collecting ... collected 2 items |   collecting ... collected 2 items | ||||||
|  | @ -128,7 +128,7 @@ select tests based on their names:: | ||||||
| 
 | 
 | ||||||
|     $ pytest -v -k http  # running with the above defined example module |     $ pytest -v -k http  # running with the above defined example module | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 |     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python | ||||||
|     cachedir: .pytest_cache |     cachedir: .pytest_cache | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collecting ... collected 4 items / 3 deselected |     collecting ... collected 4 items / 3 deselected | ||||||
|  | @ -141,7 +141,7 @@ And you can also run all tests except the ones that match the keyword:: | ||||||
| 
 | 
 | ||||||
|     $ pytest -k "not send_http" -v |     $ pytest -k "not send_http" -v | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 |     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python | ||||||
|     cachedir: .pytest_cache |     cachedir: .pytest_cache | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collecting ... collected 4 items / 1 deselected |     collecting ... collected 4 items / 1 deselected | ||||||
|  | @ -156,7 +156,7 @@ Or to select "http" and "quick" tests:: | ||||||
| 
 | 
 | ||||||
|     $ pytest -k "http or quick" -v |     $ pytest -k "http or quick" -v | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 |     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python | ||||||
|     cachedir: .pytest_cache |     cachedir: .pytest_cache | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collecting ... collected 4 items / 2 deselected |     collecting ... collected 4 items / 2 deselected | ||||||
|  |  | ||||||
|  | @ -59,7 +59,7 @@ consulted when reporting in ``verbose`` mode:: | ||||||
| 
 | 
 | ||||||
|     nonpython $ pytest -v |     nonpython $ pytest -v | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 |     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python | ||||||
|     cachedir: .pytest_cache |     cachedir: .pytest_cache | ||||||
|     rootdir: $REGENDOC_TMPDIR/nonpython, inifile: |     rootdir: $REGENDOC_TMPDIR/nonpython, inifile: | ||||||
|     collecting ... collected 2 items |     collecting ... collected 2 items | ||||||
|  |  | ||||||
|  | @ -411,11 +411,10 @@ is to be run with different sets of arguments for its three arguments: | ||||||
| Running it results in some skips if we don't have all the python interpreters installed and otherwise runs all combinations (5 interpreters times 5 interpreters times 3 objects to serialize/deserialize):: | Running it results in some skips if we don't have all the python interpreters installed and otherwise runs all combinations (5 interpreters times 5 interpreters times 3 objects to serialize/deserialize):: | ||||||
| 
 | 
 | ||||||
|    . $ pytest -rs -q multipython.py |    . $ pytest -rs -q multipython.py | ||||||
|    ...ssssssssssssssssssssssss                                          [100%] |    ...sss...sssssssss...sss...                                          [100%] | ||||||
|    ========================= short test summary info ========================== |    ========================= short test summary info ========================== | ||||||
|    SKIP [12] $REGENDOC_TMPDIR/CWD/multipython.py:29: 'python3.4' not found |    SKIP [15] $REGENDOC_TMPDIR/CWD/multipython.py:29: 'python3.4' not found | ||||||
|    SKIP [12] $REGENDOC_TMPDIR/CWD/multipython.py:29: 'python3.5' not found |    12 passed, 15 skipped in 0.12 seconds | ||||||
|    3 passed, 24 skipped in 0.12 seconds |  | ||||||
| 
 | 
 | ||||||
| Indirect parametrization of optional implementations/imports | Indirect parametrization of optional implementations/imports | ||||||
| -------------------------------------------------------------------- | -------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | @ -357,7 +357,7 @@ which will add info only when run with "--v":: | ||||||
| 
 | 
 | ||||||
|     $ pytest -v |     $ pytest -v | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 |     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python | ||||||
|     cachedir: .pytest_cache |     cachedir: .pytest_cache | ||||||
|     info1: did you know that ... |     info1: did you know that ... | ||||||
|     did you? |     did you? | ||||||
|  |  | ||||||
|  | @ -171,6 +171,7 @@ to cause the decorated ``smtp_connection`` fixture function to only be invoked | ||||||
| once per test *module* (the default is to invoke once per test *function*). | once per test *module* (the default is to invoke once per test *function*). | ||||||
| Multiple test functions in a test module will thus | Multiple test functions in a test module will thus | ||||||
| each receive the same ``smtp_connection`` fixture instance, thus saving time. | each receive the same ``smtp_connection`` fixture instance, thus saving time. | ||||||
|  | Possible values for ``scope`` are: ``function``, ``class``, ``module``, ``package`` or ``session``. | ||||||
| 
 | 
 | ||||||
| The next example puts the fixture function into a separate ``conftest.py`` file | The next example puts the fixture function into a separate ``conftest.py`` file | ||||||
| so that tests from multiple test modules in the directory can | so that tests from multiple test modules in the directory can | ||||||
|  | @ -726,7 +727,7 @@ Running this test will *skip* the invocation of ``data_set`` with value ``2``:: | ||||||
| 
 | 
 | ||||||
|     $ pytest test_fixture_marks.py -v |     $ pytest test_fixture_marks.py -v | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 |     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python | ||||||
|     cachedir: .pytest_cache |     cachedir: .pytest_cache | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collecting ... collected 3 items |     collecting ... collected 3 items | ||||||
|  | @ -769,7 +770,7 @@ Here we declare an ``app`` fixture which receives the previously defined | ||||||
| 
 | 
 | ||||||
|     $ pytest -v test_appsetup.py |     $ pytest -v test_appsetup.py | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 |     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python | ||||||
|     cachedir: .pytest_cache |     cachedir: .pytest_cache | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collecting ... collected 2 items |     collecting ... collected 2 items | ||||||
|  | @ -838,7 +839,7 @@ Let's run the tests in verbose mode and with looking at the print-output:: | ||||||
| 
 | 
 | ||||||
|     $ pytest -v -s test_module.py |     $ pytest -v -s test_module.py | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 |     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python | ||||||
|     cachedir: .pytest_cache |     cachedir: .pytest_cache | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collecting ... collected 8 items |     collecting ... collected 8 items | ||||||
|  |  | ||||||
|  | @ -255,7 +255,7 @@ Pytest supports the use of ``breakpoint()`` with the following behaviours: | ||||||
| 
 | 
 | ||||||
|  - When ``breakpoint()`` is called and ``PYTHONBREAKPOINT`` is set to the default value, pytest will use the custom internal PDB trace UI instead of the system default ``Pdb``. |  - When ``breakpoint()`` is called and ``PYTHONBREAKPOINT`` is set to the default value, pytest will use the custom internal PDB trace UI instead of the system default ``Pdb``. | ||||||
|  - When tests are complete, the system will default back to the system ``Pdb`` trace UI. |  - When tests are complete, the system will default back to the system ``Pdb`` trace UI. | ||||||
|  - If ``--pdb`` is called on execution of pytest, the custom internal Pdb trace UI is used on ``bothbreakpoint()`` and failed tests/unhandled exceptions. |  - If ``--pdb`` is called on execution of pytest, the custom internal Pdb trace UI is used on both ``breakpoint()`` and failed tests/unhandled exceptions. | ||||||
|  - If ``--pdbcls`` is used, the custom class debugger will be executed when a test fails (as expected within existing behaviour), but also when ``breakpoint()`` is called from within a test, the custom class debugger will be instantiated. |  - If ``--pdbcls`` is used, the custom class debugger will be executed when a test fails (as expected within existing behaviour), but also when ``breakpoint()`` is called from within a test, the custom class debugger will be instantiated. | ||||||
| 
 | 
 | ||||||
| .. _durations: | .. _durations: | ||||||
|  |  | ||||||
|  | @ -269,13 +269,13 @@ class AssertionRewritingHook(object): | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|     def load_module(self, name): |     def load_module(self, name): | ||||||
|  |         co, pyc = self.modules.pop(name) | ||||||
|  |         if name in sys.modules: | ||||||
|             # If there is an existing module object named 'fullname' in |             # If there is an existing module object named 'fullname' in | ||||||
|             # sys.modules, the loader must use that existing module. (Otherwise, |             # sys.modules, the loader must use that existing module. (Otherwise, | ||||||
|             # the reload() builtin will not work correctly.) |             # the reload() builtin will not work correctly.) | ||||||
|         if name in sys.modules: |             mod = sys.modules[name] | ||||||
|             return sys.modules[name] |         else: | ||||||
| 
 |  | ||||||
|         co, pyc = self.modules.pop(name) |  | ||||||
|             # I wish I could just call imp.load_compiled here, but __file__ has to |             # I wish I could just call imp.load_compiled here, but __file__ has to | ||||||
|             # be set properly. In Python 3.2+, this all would be handled correctly |             # be set properly. In Python 3.2+, this all would be handled correctly | ||||||
|             # by load_compiled. |             # by load_compiled. | ||||||
|  |  | ||||||
|  | @ -351,6 +351,7 @@ class PytestPluginManager(PluginManager): | ||||||
|             else None |             else None | ||||||
|         ) |         ) | ||||||
|         self._noconftest = namespace.noconftest |         self._noconftest = namespace.noconftest | ||||||
|  |         self._using_pyargs = namespace.pyargs | ||||||
|         testpaths = namespace.file_or_dir |         testpaths = namespace.file_or_dir | ||||||
|         foundanchor = False |         foundanchor = False | ||||||
|         for path in testpaths: |         for path in testpaths: | ||||||
|  | @ -416,7 +417,11 @@ class PytestPluginManager(PluginManager): | ||||||
|                 _ensure_removed_sysmodule(conftestpath.purebasename) |                 _ensure_removed_sysmodule(conftestpath.purebasename) | ||||||
|             try: |             try: | ||||||
|                 mod = conftestpath.pyimport() |                 mod = conftestpath.pyimport() | ||||||
|                 if hasattr(mod, "pytest_plugins") and self._configured: |                 if ( | ||||||
|  |                     hasattr(mod, "pytest_plugins") | ||||||
|  |                     and self._configured | ||||||
|  |                     and not self._using_pyargs | ||||||
|  |                 ): | ||||||
|                     from _pytest.deprecated import ( |                     from _pytest.deprecated import ( | ||||||
|                         PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST |                         PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST | ||||||
|                     ) |                     ) | ||||||
|  |  | ||||||
|  | @ -562,6 +562,9 @@ def pytest_warning_captured(warning_message, when, item): | ||||||
|         * ``"runtest"``: during test execution. |         * ``"runtest"``: during test execution. | ||||||
| 
 | 
 | ||||||
|     :param pytest.Item|None item: |     :param pytest.Item|None item: | ||||||
|  |         **DEPRECATED**: This parameter is incompatible with ``pytest-xdist``, and will always receive ``None`` | ||||||
|  |         in a future release. | ||||||
|  | 
 | ||||||
|         The item being executed if ``when`` is ``"runtest"``, otherwise ``None``. |         The item being executed if ``when`` is ``"runtest"``, otherwise ``None``. | ||||||
|     """ |     """ | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -66,7 +66,10 @@ python_keywords_allowed_list = ["or", "and", "not"] | ||||||
| 
 | 
 | ||||||
| def matchmark(colitem, markexpr): | def matchmark(colitem, markexpr): | ||||||
|     """Tries to match on any marker names, attached to the given colitem.""" |     """Tries to match on any marker names, attached to the given colitem.""" | ||||||
|  |     try: | ||||||
|         return eval(markexpr, {}, MarkMapping.from_item(colitem)) |         return eval(markexpr, {}, MarkMapping.from_item(colitem)) | ||||||
|  |     except SyntaxError as e: | ||||||
|  |         raise SyntaxError(str(e) + "\nMarker expression must be valid Python!") | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def matchkeyword(colitem, keywordexpr): | def matchkeyword(colitem, keywordexpr): | ||||||
|  |  | ||||||
|  | @ -4,9 +4,12 @@ from __future__ import absolute_import, division, print_function | ||||||
| import os | import os | ||||||
| import sys | import sys | ||||||
| import re | import re | ||||||
|  | import warnings | ||||||
| from contextlib import contextmanager | from contextlib import contextmanager | ||||||
| 
 | 
 | ||||||
| import six | import six | ||||||
|  | 
 | ||||||
|  | import pytest | ||||||
| from _pytest.fixtures import fixture | from _pytest.fixtures import fixture | ||||||
| 
 | 
 | ||||||
| RE_IMPORT_ERROR_NAME = re.compile("^No module named (.*)$") | RE_IMPORT_ERROR_NAME = re.compile("^No module named (.*)$") | ||||||
|  | @ -209,13 +212,31 @@ class MonkeyPatch(object): | ||||||
|             self._setitem.append((dic, name, dic.get(name, notset))) |             self._setitem.append((dic, name, dic.get(name, notset))) | ||||||
|             del dic[name] |             del dic[name] | ||||||
| 
 | 
 | ||||||
|  |     def _warn_if_env_name_is_not_str(self, name): | ||||||
|  |         """On Python 2, warn if the given environment variable name is not a native str (#4056)""" | ||||||
|  |         if six.PY2 and not isinstance(name, str): | ||||||
|  |             warnings.warn( | ||||||
|  |                 pytest.PytestWarning( | ||||||
|  |                     "Environment variable name {!r} should be str".format(name) | ||||||
|  |                 ) | ||||||
|  |             ) | ||||||
|  | 
 | ||||||
|     def setenv(self, name, value, prepend=None): |     def setenv(self, name, value, prepend=None): | ||||||
|         """ Set environment variable ``name`` to ``value``.  If ``prepend`` |         """ Set environment variable ``name`` to ``value``.  If ``prepend`` | ||||||
|         is a character, read the current environment variable value |         is a character, read the current environment variable value | ||||||
|         and prepend the ``value`` adjoined with the ``prepend`` character.""" |         and prepend the ``value`` adjoined with the ``prepend`` character.""" | ||||||
|  |         if not isinstance(value, str): | ||||||
|  |             warnings.warn( | ||||||
|  |                 pytest.PytestWarning( | ||||||
|  |                     "Environment variable value {!r} should be str, converted to str implicitly".format( | ||||||
|  |                         value | ||||||
|  |                     ) | ||||||
|  |                 ) | ||||||
|  |             ) | ||||||
|             value = str(value) |             value = str(value) | ||||||
|         if prepend and name in os.environ: |         if prepend and name in os.environ: | ||||||
|             value = value + prepend + os.environ[name] |             value = value + prepend + os.environ[name] | ||||||
|  |         self._warn_if_env_name_is_not_str(name) | ||||||
|         self.setitem(os.environ, name, value) |         self.setitem(os.environ, name, value) | ||||||
| 
 | 
 | ||||||
|     def delenv(self, name, raising=True): |     def delenv(self, name, raising=True): | ||||||
|  | @ -225,6 +246,7 @@ class MonkeyPatch(object): | ||||||
|         If ``raising`` is set to False, no exception will be raised if the |         If ``raising`` is set to False, no exception will be raised if the | ||||||
|         environment variable is missing. |         environment variable is missing. | ||||||
|         """ |         """ | ||||||
|  |         self._warn_if_env_name_is_not_str(name) | ||||||
|         self.delitem(os.environ, name, raising=raising) |         self.delitem(os.environ, name, raising=raising) | ||||||
| 
 | 
 | ||||||
|     def syspath_prepend(self, path): |     def syspath_prepend(self, path): | ||||||
|  |  | ||||||
|  | @ -212,6 +212,8 @@ class WarningsChecker(WarningsRecorder): | ||||||
|     def __exit__(self, *exc_info): |     def __exit__(self, *exc_info): | ||||||
|         super(WarningsChecker, self).__exit__(*exc_info) |         super(WarningsChecker, self).__exit__(*exc_info) | ||||||
| 
 | 
 | ||||||
|  |         __tracebackhide__ = True | ||||||
|  | 
 | ||||||
|         # only check if we're not currently handling an exception |         # only check if we're not currently handling an exception | ||||||
|         if all(a is None for a in exc_info): |         if all(a is None for a in exc_info): | ||||||
|             if self.expected_warning is not None: |             if self.expected_warning is not None: | ||||||
|  |  | ||||||
|  | @ -110,7 +110,7 @@ class TestReport(BaseReport): | ||||||
|         when, |         when, | ||||||
|         sections=(), |         sections=(), | ||||||
|         duration=0, |         duration=0, | ||||||
|         user_properties=(), |         user_properties=None, | ||||||
|         **extra |         **extra | ||||||
|     ): |     ): | ||||||
|         #: normalized collection node id |         #: normalized collection node id | ||||||
|  | @ -136,7 +136,7 @@ class TestReport(BaseReport): | ||||||
| 
 | 
 | ||||||
|         #: user properties is a list of tuples (name, value) that holds user |         #: user properties is a list of tuples (name, value) that holds user | ||||||
|         #: defined properties of the test |         #: defined properties of the test | ||||||
|         self.user_properties = user_properties |         self.user_properties = list(user_properties or []) | ||||||
| 
 | 
 | ||||||
|         #: list of pairs ``(str, str)`` of extra information which needs to |         #: list of pairs ``(str, str)`` of extra information which needs to | ||||||
|         #: marshallable. Used by pytest to add captured text |         #: marshallable. Used by pytest to add captured text | ||||||
|  |  | ||||||
|  | @ -745,6 +745,7 @@ class TerminalReporter(object): | ||||||
|                     return |                     return | ||||||
|                 self.write_sep("=", "PASSES") |                 self.write_sep("=", "PASSES") | ||||||
|                 for rep in reports: |                 for rep in reports: | ||||||
|  |                     if rep.sections: | ||||||
|                         msg = self._getfailureheadline(rep) |                         msg = self._getfailureheadline(rep) | ||||||
|                         self.write_sep("_", msg) |                         self.write_sep("_", msg) | ||||||
|                         self._outrep_summary(rep) |                         self._outrep_summary(rep) | ||||||
|  |  | ||||||
|  | @ -577,7 +577,7 @@ class TestInvocationVariants(object): | ||||||
|             return what |             return what | ||||||
| 
 | 
 | ||||||
|         empty_package = testdir.mkpydir("empty_package") |         empty_package = testdir.mkpydir("empty_package") | ||||||
|         monkeypatch.setenv("PYTHONPATH", join_pythonpath(empty_package)) |         monkeypatch.setenv("PYTHONPATH", str(join_pythonpath(empty_package))) | ||||||
|         # the path which is not a package raises a warning on pypy; |         # the path which is not a package raises a warning on pypy; | ||||||
|         # no idea why only pypy and not normal python warn about it here |         # no idea why only pypy and not normal python warn about it here | ||||||
|         with warnings.catch_warnings(): |         with warnings.catch_warnings(): | ||||||
|  | @ -586,7 +586,7 @@ class TestInvocationVariants(object): | ||||||
|         assert result.ret == 0 |         assert result.ret == 0 | ||||||
|         result.stdout.fnmatch_lines(["*2 passed*"]) |         result.stdout.fnmatch_lines(["*2 passed*"]) | ||||||
| 
 | 
 | ||||||
|         monkeypatch.setenv("PYTHONPATH", join_pythonpath(testdir)) |         monkeypatch.setenv("PYTHONPATH", str(join_pythonpath(testdir))) | ||||||
|         result = testdir.runpytest("--pyargs", "tpkg.test_missing", syspathinsert=True) |         result = testdir.runpytest("--pyargs", "tpkg.test_missing", syspathinsert=True) | ||||||
|         assert result.ret != 0 |         assert result.ret != 0 | ||||||
|         result.stderr.fnmatch_lines(["*not*found*test_missing*"]) |         result.stderr.fnmatch_lines(["*not*found*test_missing*"]) | ||||||
|  |  | ||||||
|  | @ -129,7 +129,7 @@ def test_source_strip_multiline(): | ||||||
| def test_syntaxerror_rerepresentation(): | def test_syntaxerror_rerepresentation(): | ||||||
|     ex = pytest.raises(SyntaxError, _pytest._code.compile, "xyz xyz") |     ex = pytest.raises(SyntaxError, _pytest._code.compile, "xyz xyz") | ||||||
|     assert ex.value.lineno == 1 |     assert ex.value.lineno == 1 | ||||||
|     assert ex.value.offset in (4, 7)  # XXX pypy/jython versus cpython? |     assert ex.value.offset in (4, 5, 7)  # XXX pypy/jython versus cpython? | ||||||
|     assert ex.value.text.strip(), "x x" |     assert ex.value.text.strip(), "x x" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -246,21 +246,12 @@ def test_pytest_catchlog_deprecated(testdir, plugin): | ||||||
| def test_pytest_plugins_in_non_top_level_conftest_deprecated(testdir): | def test_pytest_plugins_in_non_top_level_conftest_deprecated(testdir): | ||||||
|     from _pytest.deprecated import PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST |     from _pytest.deprecated import PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST | ||||||
| 
 | 
 | ||||||
|     subdirectory = testdir.tmpdir.join("subdirectory") |     testdir.makepyfile( | ||||||
|     subdirectory.mkdir() |         **{ | ||||||
|     # create the inner conftest with makeconftest and then move it to the subdirectory |             "subdirectory/conftest.py": """ | ||||||
|     testdir.makeconftest( |  | ||||||
|         """ |  | ||||||
|         pytest_plugins=['capture'] |         pytest_plugins=['capture'] | ||||||
|     """ |     """ | ||||||
|     ) |         } | ||||||
|     testdir.tmpdir.join("conftest.py").move(subdirectory.join("conftest.py")) |  | ||||||
|     # make the top level conftest |  | ||||||
|     testdir.makeconftest( |  | ||||||
|         """ |  | ||||||
|         import warnings |  | ||||||
|         warnings.filterwarnings('always', category=DeprecationWarning) |  | ||||||
|     """ |  | ||||||
|     ) |     ) | ||||||
|     testdir.makepyfile( |     testdir.makepyfile( | ||||||
|         """ |         """ | ||||||
|  | @ -268,7 +259,7 @@ def test_pytest_plugins_in_non_top_level_conftest_deprecated(testdir): | ||||||
|             pass |             pass | ||||||
|     """ |     """ | ||||||
|     ) |     ) | ||||||
|     res = testdir.runpytest_subprocess() |     res = testdir.runpytest() | ||||||
|     assert res.ret == 0 |     assert res.ret == 0 | ||||||
|     msg = str(PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST).splitlines()[0] |     msg = str(PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST).splitlines()[0] | ||||||
|     res.stdout.fnmatch_lines( |     res.stdout.fnmatch_lines( | ||||||
|  | @ -278,6 +269,34 @@ def test_pytest_plugins_in_non_top_level_conftest_deprecated(testdir): | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @pytest.mark.parametrize("use_pyargs", [True, False]) | ||||||
|  | def test_pytest_plugins_in_non_top_level_conftest_deprecated_pyargs( | ||||||
|  |     testdir, use_pyargs | ||||||
|  | ): | ||||||
|  |     """When using --pyargs, do not emit the warning about non-top-level conftest warnings (#4039, #4044)""" | ||||||
|  |     from _pytest.deprecated import PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST | ||||||
|  | 
 | ||||||
|  |     files = { | ||||||
|  |         "src/pkg/__init__.py": "", | ||||||
|  |         "src/pkg/conftest.py": "", | ||||||
|  |         "src/pkg/test_root.py": "def test(): pass", | ||||||
|  |         "src/pkg/sub/__init__.py": "", | ||||||
|  |         "src/pkg/sub/conftest.py": "pytest_plugins=['capture']", | ||||||
|  |         "src/pkg/sub/test_bar.py": "def test(): pass", | ||||||
|  |     } | ||||||
|  |     testdir.makepyfile(**files) | ||||||
|  |     testdir.syspathinsert(testdir.tmpdir.join("src")) | ||||||
|  | 
 | ||||||
|  |     args = ("--pyargs", "pkg") if use_pyargs else () | ||||||
|  |     res = testdir.runpytest(*args) | ||||||
|  |     assert res.ret == 0 | ||||||
|  |     msg = str(PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST).splitlines()[0] | ||||||
|  |     if use_pyargs: | ||||||
|  |         assert msg not in res.stdout.str() | ||||||
|  |     else: | ||||||
|  |         res.stdout.fnmatch_lines("*{msg}*".format(msg=msg)) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| def test_pytest_plugins_in_non_top_level_conftest_deprecated_no_top_level_conftest( | def test_pytest_plugins_in_non_top_level_conftest_deprecated_no_top_level_conftest( | ||||||
|     testdir |     testdir | ||||||
| ): | ): | ||||||
|  |  | ||||||
|  | @ -1050,6 +1050,48 @@ class TestAssertionRewriteHookDetails(object): | ||||||
|         result = testdir.runpytest("-s") |         result = testdir.runpytest("-s") | ||||||
|         result.stdout.fnmatch_lines(["* 1 passed*"]) |         result.stdout.fnmatch_lines(["* 1 passed*"]) | ||||||
| 
 | 
 | ||||||
|  |     def test_reload_reloads(self, testdir): | ||||||
|  |         """Reloading a module after change picks up the change.""" | ||||||
|  |         testdir.tmpdir.join("file.py").write( | ||||||
|  |             textwrap.dedent( | ||||||
|  |                 """ | ||||||
|  |             def reloaded(): | ||||||
|  |                 return False | ||||||
|  | 
 | ||||||
|  |             def rewrite_self(): | ||||||
|  |                 with open(__file__, 'w') as self: | ||||||
|  |                     self.write('def reloaded(): return True') | ||||||
|  |         """ | ||||||
|  |             ) | ||||||
|  |         ) | ||||||
|  |         testdir.tmpdir.join("pytest.ini").write( | ||||||
|  |             textwrap.dedent( | ||||||
|  |                 """ | ||||||
|  |             [pytest] | ||||||
|  |             python_files = *.py | ||||||
|  |         """ | ||||||
|  |             ) | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |         testdir.makepyfile( | ||||||
|  |             test_fun=""" | ||||||
|  |             import sys | ||||||
|  |             try: | ||||||
|  |                 from imp import reload | ||||||
|  |             except ImportError: | ||||||
|  |                 pass | ||||||
|  | 
 | ||||||
|  |             def test_loader(): | ||||||
|  |                 import file | ||||||
|  |                 assert not file.reloaded() | ||||||
|  |                 file.rewrite_self() | ||||||
|  |                 reload(file) | ||||||
|  |                 assert file.reloaded() | ||||||
|  |             """ | ||||||
|  |         ) | ||||||
|  |         result = testdir.runpytest("-s") | ||||||
|  |         result.stdout.fnmatch_lines(["* 1 passed*"]) | ||||||
|  | 
 | ||||||
|     def test_get_data_support(self, testdir): |     def test_get_data_support(self, testdir): | ||||||
|         """Implement optional PEP302 api (#808). |         """Implement optional PEP302 api (#808). | ||||||
|         """ |         """ | ||||||
|  |  | ||||||
|  | @ -215,7 +215,7 @@ def test_cache_show(testdir): | ||||||
| 
 | 
 | ||||||
| class TestLastFailed(object): | class TestLastFailed(object): | ||||||
|     def test_lastfailed_usecase(self, testdir, monkeypatch): |     def test_lastfailed_usecase(self, testdir, monkeypatch): | ||||||
|         monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", 1) |         monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", "1") | ||||||
|         p = testdir.makepyfile( |         p = testdir.makepyfile( | ||||||
|             """ |             """ | ||||||
|             def test_1(): |             def test_1(): | ||||||
|  | @ -301,7 +301,7 @@ class TestLastFailed(object): | ||||||
|         assert "test_a.py" not in result.stdout.str() |         assert "test_a.py" not in result.stdout.str() | ||||||
| 
 | 
 | ||||||
|     def test_lastfailed_difference_invocations(self, testdir, monkeypatch): |     def test_lastfailed_difference_invocations(self, testdir, monkeypatch): | ||||||
|         monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", 1) |         monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", "1") | ||||||
|         testdir.makepyfile( |         testdir.makepyfile( | ||||||
|             test_a="""\ |             test_a="""\ | ||||||
|             def test_a1(): |             def test_a1(): | ||||||
|  | @ -335,7 +335,7 @@ class TestLastFailed(object): | ||||||
|         result.stdout.fnmatch_lines(["*1 failed*1 desel*"]) |         result.stdout.fnmatch_lines(["*1 failed*1 desel*"]) | ||||||
| 
 | 
 | ||||||
|     def test_lastfailed_usecase_splice(self, testdir, monkeypatch): |     def test_lastfailed_usecase_splice(self, testdir, monkeypatch): | ||||||
|         monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", 1) |         monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", "1") | ||||||
|         testdir.makepyfile( |         testdir.makepyfile( | ||||||
|             """\ |             """\ | ||||||
|             def test_1(): |             def test_1(): | ||||||
|  | @ -474,8 +474,8 @@ class TestLastFailed(object): | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|         def rlf(fail_import, fail_run): |         def rlf(fail_import, fail_run): | ||||||
|             monkeypatch.setenv("FAILIMPORT", fail_import) |             monkeypatch.setenv("FAILIMPORT", str(fail_import)) | ||||||
|             monkeypatch.setenv("FAILTEST", fail_run) |             monkeypatch.setenv("FAILTEST", str(fail_run)) | ||||||
| 
 | 
 | ||||||
|             testdir.runpytest("-q") |             testdir.runpytest("-q") | ||||||
|             config = testdir.parseconfigure() |             config = testdir.parseconfigure() | ||||||
|  | @ -519,8 +519,8 @@ class TestLastFailed(object): | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|         def rlf(fail_import, fail_run, args=()): |         def rlf(fail_import, fail_run, args=()): | ||||||
|             monkeypatch.setenv("FAILIMPORT", fail_import) |             monkeypatch.setenv("FAILIMPORT", str(fail_import)) | ||||||
|             monkeypatch.setenv("FAILTEST", fail_run) |             monkeypatch.setenv("FAILTEST", str(fail_run)) | ||||||
| 
 | 
 | ||||||
|             result = testdir.runpytest("-q", "--lf", *args) |             result = testdir.runpytest("-q", "--lf", *args) | ||||||
|             config = testdir.parseconfigure() |             config = testdir.parseconfigure() | ||||||
|  |  | ||||||
|  | @ -30,6 +30,7 @@ def conftest_setinitial(conftest, args, confcutdir=None): | ||||||
|             self.file_or_dir = args |             self.file_or_dir = args | ||||||
|             self.confcutdir = str(confcutdir) |             self.confcutdir = str(confcutdir) | ||||||
|             self.noconftest = False |             self.noconftest = False | ||||||
|  |             self.pyargs = False | ||||||
| 
 | 
 | ||||||
|     conftest._set_initial_conftests(Namespace()) |     conftest._set_initial_conftests(Namespace()) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -850,7 +850,7 @@ def test_logxml_path_expansion(tmpdir, monkeypatch): | ||||||
|     assert xml_tilde.logfile == home_tilde |     assert xml_tilde.logfile == home_tilde | ||||||
| 
 | 
 | ||||||
|     # this is here for when $HOME is not set correct |     # this is here for when $HOME is not set correct | ||||||
|     monkeypatch.setenv("HOME", tmpdir) |     monkeypatch.setenv("HOME", str(tmpdir)) | ||||||
|     home_var = os.path.normpath(os.path.expandvars("$HOME/test.xml")) |     home_var = os.path.normpath(os.path.expandvars("$HOME/test.xml")) | ||||||
| 
 | 
 | ||||||
|     xml_var = LogXML("$HOME%stest.xml" % tmpdir.sep, None) |     xml_var = LogXML("$HOME%stest.xml" % tmpdir.sep, None) | ||||||
|  |  | ||||||
|  | @ -799,6 +799,18 @@ class TestFunctional(object): | ||||||
|         deselected_tests = dlist[0].items |         deselected_tests = dlist[0].items | ||||||
|         assert len(deselected_tests) == 2 |         assert len(deselected_tests) == 2 | ||||||
| 
 | 
 | ||||||
|  |     def test_invalid_m_option(self, testdir): | ||||||
|  |         testdir.makepyfile( | ||||||
|  |             """ | ||||||
|  |             def test_a(): | ||||||
|  |                 pass | ||||||
|  |         """ | ||||||
|  |         ) | ||||||
|  |         result = testdir.runpytest("-m bogus/") | ||||||
|  |         result.stdout.fnmatch_lines( | ||||||
|  |             ["INTERNALERROR> Marker expression must be valid Python!"] | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|     def test_keywords_at_node_level(self, testdir): |     def test_keywords_at_node_level(self, testdir): | ||||||
|         testdir.makepyfile( |         testdir.makepyfile( | ||||||
|             """ |             """ | ||||||
|  |  | ||||||
|  | @ -3,6 +3,8 @@ import os | ||||||
| import sys | import sys | ||||||
| import textwrap | import textwrap | ||||||
| 
 | 
 | ||||||
|  | import six | ||||||
|  | 
 | ||||||
| import pytest | import pytest | ||||||
| from _pytest.monkeypatch import MonkeyPatch | from _pytest.monkeypatch import MonkeyPatch | ||||||
| 
 | 
 | ||||||
|  | @ -163,6 +165,7 @@ def test_delitem(): | ||||||
| 
 | 
 | ||||||
| def test_setenv(): | def test_setenv(): | ||||||
|     monkeypatch = MonkeyPatch() |     monkeypatch = MonkeyPatch() | ||||||
|  |     with pytest.warns(pytest.PytestWarning): | ||||||
|         monkeypatch.setenv("XYZ123", 2) |         monkeypatch.setenv("XYZ123", 2) | ||||||
|     import os |     import os | ||||||
| 
 | 
 | ||||||
|  | @ -192,12 +195,48 @@ def test_delenv(): | ||||||
|             del os.environ[name] |             del os.environ[name] | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | class TestEnvironWarnings(object): | ||||||
|  |     """ | ||||||
|  |     os.environ keys and values should be native strings, otherwise it will cause problems with other modules (notably | ||||||
|  |     subprocess). On Python 2 os.environ accepts anything without complaining, while Python 3 does the right thing | ||||||
|  |     and raises an error. | ||||||
|  |     """ | ||||||
|  | 
 | ||||||
|  |     VAR_NAME = u"PYTEST_INTERNAL_MY_VAR" | ||||||
|  | 
 | ||||||
|  |     @pytest.mark.skipif(six.PY3, reason="Python 2 only test") | ||||||
|  |     def test_setenv_unicode_key(self, monkeypatch): | ||||||
|  |         with pytest.warns( | ||||||
|  |             pytest.PytestWarning, | ||||||
|  |             match="Environment variable name {!r} should be str".format(self.VAR_NAME), | ||||||
|  |         ): | ||||||
|  |             monkeypatch.setenv(self.VAR_NAME, "2") | ||||||
|  | 
 | ||||||
|  |     @pytest.mark.skipif(six.PY3, reason="Python 2 only test") | ||||||
|  |     def test_delenv_unicode_key(self, monkeypatch): | ||||||
|  |         with pytest.warns( | ||||||
|  |             pytest.PytestWarning, | ||||||
|  |             match="Environment variable name {!r} should be str".format(self.VAR_NAME), | ||||||
|  |         ): | ||||||
|  |             monkeypatch.delenv(self.VAR_NAME, raising=False) | ||||||
|  | 
 | ||||||
|  |     def test_setenv_non_str_warning(self, monkeypatch): | ||||||
|  |         value = 2 | ||||||
|  |         msg = ( | ||||||
|  |             "Environment variable value {!r} should be str, converted to str implicitly" | ||||||
|  |         ) | ||||||
|  |         with pytest.warns(pytest.PytestWarning, match=msg.format(value)): | ||||||
|  |             monkeypatch.setenv(str(self.VAR_NAME), value) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| def test_setenv_prepend(): | def test_setenv_prepend(): | ||||||
|     import os |     import os | ||||||
| 
 | 
 | ||||||
|     monkeypatch = MonkeyPatch() |     monkeypatch = MonkeyPatch() | ||||||
|  |     with pytest.warns(pytest.PytestWarning): | ||||||
|         monkeypatch.setenv("XYZ123", 2, prepend="-") |         monkeypatch.setenv("XYZ123", 2, prepend="-") | ||||||
|     assert os.environ["XYZ123"] == "2" |     assert os.environ["XYZ123"] == "2" | ||||||
|  |     with pytest.warns(pytest.PytestWarning): | ||||||
|         monkeypatch.setenv("XYZ123", 3, prepend="-") |         monkeypatch.setenv("XYZ123", 3, prepend="-") | ||||||
|     assert os.environ["XYZ123"] == "3-2" |     assert os.environ["XYZ123"] == "3-2" | ||||||
|     monkeypatch.undo() |     monkeypatch.undo() | ||||||
|  |  | ||||||
|  | @ -681,14 +681,22 @@ def test_pass_reporting_on_fail(testdir): | ||||||
| def test_pass_output_reporting(testdir): | def test_pass_output_reporting(testdir): | ||||||
|     testdir.makepyfile( |     testdir.makepyfile( | ||||||
|         """ |         """ | ||||||
|         def test_pass_output(): |         def test_pass_has_output(): | ||||||
|             print("Four score and seven years ago...") |             print("Four score and seven years ago...") | ||||||
|  |         def test_pass_no_output(): | ||||||
|  |             pass | ||||||
|     """ |     """ | ||||||
|     ) |     ) | ||||||
|     result = testdir.runpytest() |     result = testdir.runpytest() | ||||||
|     assert "Four score and seven years ago..." not in result.stdout.str() |     s = result.stdout.str() | ||||||
|  |     assert "test_pass_has_output" not in s | ||||||
|  |     assert "Four score and seven years ago..." not in s | ||||||
|  |     assert "test_pass_no_output" not in s | ||||||
|     result = testdir.runpytest("-rP") |     result = testdir.runpytest("-rP") | ||||||
|     result.stdout.fnmatch_lines(["Four score and seven years ago..."]) |     result.stdout.fnmatch_lines( | ||||||
|  |         ["*test_pass_has_output*", "Four score and seven years ago..."] | ||||||
|  |     ) | ||||||
|  |     assert "test_pass_no_output" not in result.stdout.str() | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def test_color_yes(testdir): | def test_color_yes(testdir): | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue