Merge remote-tracking branch 'upstream/master' into merge-master-into-features
This commit is contained in:
		
						commit
						33b877cc01
					
				
							
								
								
									
										1
									
								
								AUTHORS
								
								
								
								
							
							
						
						
									
										1
									
								
								AUTHORS
								
								
								
								
							|  | @ -159,6 +159,7 @@ Michael Droettboom | ||||||
| Michael Seifert | Michael Seifert | ||||||
| Michal Wajszczuk | Michal Wajszczuk | ||||||
| Mihai Capotă | Mihai Capotă | ||||||
|  | Mike Hoyle (hoylemd) | ||||||
| Mike Lundy | Mike Lundy | ||||||
| Miro Hrončok | Miro Hrončok | ||||||
| Nathaniel Waisbrot | Nathaniel Waisbrot | ||||||
|  |  | ||||||
|  | @ -18,6 +18,43 @@ with advance notice in the **Deprecations** section of releases. | ||||||
| 
 | 
 | ||||||
| .. towncrier release notes start | .. towncrier release notes start | ||||||
| 
 | 
 | ||||||
|  | pytest 4.0.1 (2018-11-23) | ||||||
|  | ========================= | ||||||
|  | 
 | ||||||
|  | Bug Fixes | ||||||
|  | --------- | ||||||
|  | 
 | ||||||
|  | - `#3952 <https://github.com/pytest-dev/pytest/issues/3952>`_: Display warnings before "short test summary info" again, but still later warnings in the end. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | - `#4386 <https://github.com/pytest-dev/pytest/issues/4386>`_: Handle uninitialized exceptioninfo in repr/str. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | - `#4393 <https://github.com/pytest-dev/pytest/issues/4393>`_: Do not create ``.gitignore``/``README.md`` files in existing cache directories. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | - `#4400 <https://github.com/pytest-dev/pytest/issues/4400>`_: Rearrange warning handling for the yield test errors so the opt-out in 4.0.x correctly works. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | - `#4405 <https://github.com/pytest-dev/pytest/issues/4405>`_: Fix collection of testpaths with ``--pyargs``. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | - `#4412 <https://github.com/pytest-dev/pytest/issues/4412>`_: Fix assertion rewriting involving ``Starred`` + side-effects. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | - `#4425 <https://github.com/pytest-dev/pytest/issues/4425>`_: Ensure we resolve the absolute path when the given ``--basetemp`` is a relative path. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | Trivial/Internal Changes | ||||||
|  | ------------------------ | ||||||
|  | 
 | ||||||
|  | - `#4315 <https://github.com/pytest-dev/pytest/issues/4315>`_: Use ``pkg_resources.parse_version`` instead of ``LooseVersion`` in minversion check. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | - `#4440 <https://github.com/pytest-dev/pytest/issues/4440>`_: Adjust the stack level of some internal pytest warnings. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| pytest 4.0.0 (2018-11-13) | pytest 4.0.0 (2018-11-13) | ||||||
| ========================= | ========================= | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1 +0,0 @@ | ||||||
| Rearrange warning handling for the yield test errors so the opt-out in 4.0.x correctly works. |  | ||||||
|  | @ -1 +0,0 @@ | ||||||
| Fix collection of testpaths with ``--pyargs``. |  | ||||||
|  | @ -1 +0,0 @@ | ||||||
| Fix assertion rewriting involving ``Starred`` + side-effects. |  | ||||||
|  | @ -6,6 +6,7 @@ Release announcements | ||||||
|    :maxdepth: 2 |    :maxdepth: 2 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |    release-4.0.1 | ||||||
|    release-4.0.0 |    release-4.0.0 | ||||||
|    release-3.10.1 |    release-3.10.1 | ||||||
|    release-3.10.0 |    release-3.10.0 | ||||||
|  |  | ||||||
|  | @ -0,0 +1,23 @@ | ||||||
|  | pytest-4.0.1 | ||||||
|  | ======================================= | ||||||
|  | 
 | ||||||
|  | pytest 4.0.1 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: | ||||||
|  | 
 | ||||||
|  | * Anthony Sottile | ||||||
|  | * Bruno Oliveira | ||||||
|  | * Daniel Hahler | ||||||
|  | * Michael D. Hoyle | ||||||
|  | * Ronny Pfannschmidt | ||||||
|  | * Slam | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | Happy testing, | ||||||
|  | The pytest Development Team | ||||||
|  | @ -26,7 +26,7 @@ you will see the return value of the function call:: | ||||||
| 
 | 
 | ||||||
|     $ pytest test_assert1.py |     $ pytest test_assert1.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 |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 1 item |     collected 1 item | ||||||
| 
 | 
 | ||||||
|  | @ -169,7 +169,7 @@ if you run this module:: | ||||||
| 
 | 
 | ||||||
|     $ pytest test_assert2.py |     $ pytest test_assert2.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 |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 1 item |     collected 1 item | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -76,7 +76,7 @@ If you then run it with ``--lf``:: | ||||||
| 
 | 
 | ||||||
|     $ pytest --lf |     $ pytest --lf | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 50 items / 48 deselected |     collected 50 items / 48 deselected | ||||||
|     run-last-failure: rerun previous 2 failures |     run-last-failure: rerun previous 2 failures | ||||||
|  | @ -117,7 +117,7 @@ of ``FF`` and dots):: | ||||||
| 
 | 
 | ||||||
|     $ pytest --ff |     $ pytest --ff | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 50 items |     collected 50 items | ||||||
|     run-last-failure: rerun previous 2 failures first |     run-last-failure: rerun previous 2 failures first | ||||||
|  | @ -236,7 +236,7 @@ You can always peek at the content of the cache using the | ||||||
| 
 | 
 | ||||||
|     $ pytest --cache-show |     $ pytest --cache-show | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     cachedir: $REGENDOC_TMPDIR/.pytest_cache |     cachedir: $REGENDOC_TMPDIR/.pytest_cache | ||||||
|     ------------------------------- cache values ------------------------------- |     ------------------------------- cache values ------------------------------- | ||||||
|  |  | ||||||
|  | @ -52,7 +52,7 @@ is that you can use print statements for debugging:: | ||||||
|     # content of test_module.py |     # content of test_module.py | ||||||
| 
 | 
 | ||||||
|     def setup_function(function): |     def setup_function(function): | ||||||
|         print ("setting up %s" % function) |         print("setting up %s" % function) | ||||||
| 
 | 
 | ||||||
|     def test_func1(): |     def test_func1(): | ||||||
|         assert True |         assert True | ||||||
|  | @ -65,7 +65,7 @@ of the failing function and hide the other one:: | ||||||
| 
 | 
 | ||||||
|     $ pytest |     $ pytest | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 2 items |     collected 2 items | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -62,7 +62,7 @@ then you can just invoke ``pytest`` without command line options:: | ||||||
| 
 | 
 | ||||||
|     $ pytest |     $ pytest | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini |     rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini | ||||||
|     collected 1 item |     collected 1 item | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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-4.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 | ||||||
|     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-4.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 | ||||||
|     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-4.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 | ||||||
|     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-4.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 | ||||||
|     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-4.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 | ||||||
|   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-4.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 | ||||||
|     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-4.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 | ||||||
|     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-4.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 | ||||||
|     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 | ||||||
|  | @ -271,8 +271,12 @@ You can also set a module level marker:: | ||||||
|     import pytest |     import pytest | ||||||
|     pytestmark = pytest.mark.webtest |     pytestmark = pytest.mark.webtest | ||||||
| 
 | 
 | ||||||
| in which case it will be applied to all functions and | or multiple markers:: | ||||||
| methods defined in the module. | 
 | ||||||
|  |     pytestmark = [pytest.mark.webtest, pytest.mark.slowtest] | ||||||
|  | 
 | ||||||
|  | in which case markers will be applied (in left-to-right order) to | ||||||
|  | all functions and methods defined in the module. | ||||||
| 
 | 
 | ||||||
| .. _`marking individual tests when using parametrize`: | .. _`marking individual tests when using parametrize`: | ||||||
| 
 | 
 | ||||||
|  | @ -351,7 +355,7 @@ the test needs:: | ||||||
| 
 | 
 | ||||||
|     $ pytest -E stage2 |     $ pytest -E stage2 | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 1 item |     collected 1 item | ||||||
| 
 | 
 | ||||||
|  | @ -363,7 +367,7 @@ and here is one that specifies exactly the environment needed:: | ||||||
| 
 | 
 | ||||||
|     $ pytest -E stage1 |     $ pytest -E stage1 | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 1 item |     collected 1 item | ||||||
| 
 | 
 | ||||||
|  | @ -462,7 +466,7 @@ test function.  From a conftest file we can read it like this:: | ||||||
| 
 | 
 | ||||||
|     def pytest_runtest_setup(item): |     def pytest_runtest_setup(item): | ||||||
|         for mark in item.iter_markers(name='glob'): |         for mark in item.iter_markers(name='glob'): | ||||||
|             print ("glob args=%s kwargs=%s" %(mark.args, mark.kwargs)) |             print("glob args=%s kwargs=%s" % (mark.args, mark.kwargs)) | ||||||
|             sys.stdout.flush() |             sys.stdout.flush() | ||||||
| 
 | 
 | ||||||
| Let's run this without capturing output and see what we get:: | Let's run this without capturing output and see what we get:: | ||||||
|  | @ -524,7 +528,7 @@ then you will see two tests skipped and two executed tests as expected:: | ||||||
| 
 | 
 | ||||||
|     $ pytest -rs # this option reports skip reasons |     $ pytest -rs # this option reports skip reasons | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 4 items |     collected 4 items | ||||||
| 
 | 
 | ||||||
|  | @ -538,7 +542,7 @@ Note that if you specify a platform via the marker-command line option like this | ||||||
| 
 | 
 | ||||||
|     $ pytest -m linux |     $ pytest -m linux | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 4 items / 3 deselected |     collected 4 items / 3 deselected | ||||||
| 
 | 
 | ||||||
|  | @ -589,7 +593,7 @@ We can now use the ``-m option`` to select one set:: | ||||||
| 
 | 
 | ||||||
|   $ pytest -m interface --tb=short |   $ pytest -m interface --tb=short | ||||||
|   =========================== test session starts ============================ |   =========================== test session starts ============================ | ||||||
|   platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y |   platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|   rootdir: $REGENDOC_TMPDIR, inifile: |   rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|   collected 4 items / 2 deselected |   collected 4 items / 2 deselected | ||||||
| 
 | 
 | ||||||
|  | @ -610,7 +614,7 @@ or to select both "event" and "interface" tests:: | ||||||
| 
 | 
 | ||||||
|   $ pytest -m "interface or event" --tb=short |   $ pytest -m "interface or event" --tb=short | ||||||
|   =========================== test session starts ============================ |   =========================== test session starts ============================ | ||||||
|   platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y |   platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|   rootdir: $REGENDOC_TMPDIR, inifile: |   rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|   collected 4 items / 1 deselected |   collected 4 items / 1 deselected | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -27,7 +27,7 @@ now execute the test specification:: | ||||||
| 
 | 
 | ||||||
|     nonpython $ pytest test_simple.yml |     nonpython $ pytest test_simple.yml | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR/nonpython, inifile: |     rootdir: $REGENDOC_TMPDIR/nonpython, inifile: | ||||||
|     collected 2 items |     collected 2 items | ||||||
| 
 | 
 | ||||||
|  | @ -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-4.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 | ||||||
|     cachedir: .pytest_cache |     cachedir: .pytest_cache | ||||||
|     rootdir: $REGENDOC_TMPDIR/nonpython, inifile: |     rootdir: $REGENDOC_TMPDIR/nonpython, inifile: | ||||||
|     collecting ... collected 2 items |     collecting ... collected 2 items | ||||||
|  | @ -81,7 +81,7 @@ interesting to just look at the collection tree:: | ||||||
| 
 | 
 | ||||||
|     nonpython $ pytest --collect-only |     nonpython $ pytest --collect-only | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR/nonpython, inifile: |     rootdir: $REGENDOC_TMPDIR/nonpython, inifile: | ||||||
|     collected 2 items |     collected 2 items | ||||||
|     <Package '$REGENDOC_TMPDIR/nonpython'> |     <Package '$REGENDOC_TMPDIR/nonpython'> | ||||||
|  |  | ||||||
|  | @ -139,7 +139,7 @@ objects, they are still using the default pytest representation:: | ||||||
| 
 | 
 | ||||||
|     $ pytest test_time.py --collect-only |     $ pytest test_time.py --collect-only | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 8 items |     collected 8 items | ||||||
|     <Module 'test_time.py'> |     <Module 'test_time.py'> | ||||||
|  | @ -195,7 +195,7 @@ this is a fully self-contained example which you can run with:: | ||||||
| 
 | 
 | ||||||
|     $ pytest test_scenarios.py |     $ pytest test_scenarios.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 |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 4 items |     collected 4 items | ||||||
| 
 | 
 | ||||||
|  | @ -208,7 +208,7 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia | ||||||
| 
 | 
 | ||||||
|     $ pytest --collect-only test_scenarios.py |     $ pytest --collect-only test_scenarios.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 |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 4 items |     collected 4 items | ||||||
|     <Module 'test_scenarios.py'> |     <Module 'test_scenarios.py'> | ||||||
|  | @ -272,7 +272,7 @@ Let's first see how it looks like at collection time:: | ||||||
| 
 | 
 | ||||||
|     $ pytest test_backends.py --collect-only |     $ pytest test_backends.py --collect-only | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 2 items |     collected 2 items | ||||||
|     <Module 'test_backends.py'> |     <Module 'test_backends.py'> | ||||||
|  | @ -333,7 +333,7 @@ The result of this test will be successful:: | ||||||
| 
 | 
 | ||||||
|     $ pytest test_indirect_list.py --collect-only |     $ pytest test_indirect_list.py --collect-only | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 1 item |     collected 1 item | ||||||
|     <Module 'test_indirect_list.py'> |     <Module 'test_indirect_list.py'> | ||||||
|  | @ -460,7 +460,7 @@ If you run this with reporting for skips enabled:: | ||||||
| 
 | 
 | ||||||
|     $ pytest -rs test_module.py |     $ pytest -rs 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 |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 2 items |     collected 2 items | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -127,7 +127,7 @@ The test collection would look like this:: | ||||||
| 
 | 
 | ||||||
|     $ pytest --collect-only |     $ pytest --collect-only | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini |     rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini | ||||||
|     collected 2 items |     collected 2 items | ||||||
|     <Module 'check_myapp.py'> |     <Module 'check_myapp.py'> | ||||||
|  | @ -180,7 +180,7 @@ You can always peek at the collection tree without running tests like this:: | ||||||
| 
 | 
 | ||||||
|     . $ pytest --collect-only pythoncollection.py |     . $ pytest --collect-only pythoncollection.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 |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini |     rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini | ||||||
|     collected 3 items |     collected 3 items | ||||||
|     <Module 'CWD/pythoncollection.py'> |     <Module 'CWD/pythoncollection.py'> | ||||||
|  | @ -248,7 +248,7 @@ file will be left out:: | ||||||
| 
 | 
 | ||||||
|     $ pytest --collect-only |     $ pytest --collect-only | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini |     rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini | ||||||
|     collected 0 items |     collected 0 items | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -11,7 +11,7 @@ get on the terminal - we are working on that):: | ||||||
| 
 | 
 | ||||||
|     assertion $ pytest failure_demo.py |     assertion $ pytest failure_demo.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 |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR/assertion, inifile: |     rootdir: $REGENDOC_TMPDIR/assertion, inifile: | ||||||
|     collected 42 items |     collected 42 items | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -121,7 +121,7 @@ directory with the above conftest.py:: | ||||||
| 
 | 
 | ||||||
|     $ pytest |     $ pytest | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 0 items |     collected 0 items | ||||||
| 
 | 
 | ||||||
|  | @ -179,7 +179,7 @@ and when running it will see a skipped "slow" test:: | ||||||
| 
 | 
 | ||||||
|     $ pytest -rs    # "-rs" means report details on the little 's' |     $ pytest -rs    # "-rs" means report details on the little 's' | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 2 items |     collected 2 items | ||||||
| 
 | 
 | ||||||
|  | @ -193,7 +193,7 @@ Or run it including the ``slow`` marked test:: | ||||||
| 
 | 
 | ||||||
|     $ pytest --runslow |     $ pytest --runslow | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 2 items |     collected 2 items | ||||||
| 
 | 
 | ||||||
|  | @ -331,7 +331,7 @@ which will add the string to the test header accordingly:: | ||||||
| 
 | 
 | ||||||
|     $ pytest |     $ pytest | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     project deps: mylib-1.1 |     project deps: mylib-1.1 | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 0 items |     collected 0 items | ||||||
|  | @ -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-4.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 | ||||||
|     cachedir: .pytest_cache |     cachedir: .pytest_cache | ||||||
|     info1: did you know that ... |     info1: did you know that ... | ||||||
|     did you? |     did you? | ||||||
|  | @ -370,7 +370,7 @@ and nothing when run plainly:: | ||||||
| 
 | 
 | ||||||
|     $ pytest |     $ pytest | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 0 items |     collected 0 items | ||||||
| 
 | 
 | ||||||
|  | @ -407,7 +407,7 @@ Now we can profile which test functions execute the slowest:: | ||||||
| 
 | 
 | ||||||
|     $ pytest --durations=3 |     $ pytest --durations=3 | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 3 items |     collected 3 items | ||||||
| 
 | 
 | ||||||
|  | @ -479,7 +479,7 @@ If we run this:: | ||||||
| 
 | 
 | ||||||
|     $ pytest -rx |     $ pytest -rx | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 4 items |     collected 4 items | ||||||
| 
 | 
 | ||||||
|  | @ -560,7 +560,7 @@ We can run this:: | ||||||
| 
 | 
 | ||||||
|     $ pytest |     $ pytest | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 7 items |     collected 7 items | ||||||
| 
 | 
 | ||||||
|  | @ -671,7 +671,7 @@ and run them:: | ||||||
| 
 | 
 | ||||||
|     $ pytest test_module.py |     $ pytest 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 |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 2 items |     collected 2 items | ||||||
| 
 | 
 | ||||||
|  | @ -770,7 +770,7 @@ and run it:: | ||||||
| 
 | 
 | ||||||
|     $ pytest -s test_module.py |     $ pytest -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 |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 3 items |     collected 3 items | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -13,7 +13,7 @@ calls it:: | ||||||
| 
 | 
 | ||||||
|     @pytest.fixture(scope="session", autouse=True) |     @pytest.fixture(scope="session", autouse=True) | ||||||
|     def callattr_ahead_of_alltests(request): |     def callattr_ahead_of_alltests(request): | ||||||
|         print ("callattr_ahead_of_alltests called") |         print("callattr_ahead_of_alltests called") | ||||||
|         seen = set([None]) |         seen = set([None]) | ||||||
|         session = request.node |         session = request.node | ||||||
|         for item in session.items: |         for item in session.items: | ||||||
|  | @ -31,20 +31,20 @@ will be called ahead of running any tests:: | ||||||
|     class TestHello(object): |     class TestHello(object): | ||||||
|         @classmethod |         @classmethod | ||||||
|         def callme(cls): |         def callme(cls): | ||||||
|             print ("callme called!") |             print("callme called!") | ||||||
| 
 | 
 | ||||||
|         def test_method1(self): |         def test_method1(self): | ||||||
|             print ("test_method1 called") |             print("test_method1 called") | ||||||
| 
 | 
 | ||||||
|         def test_method2(self): |         def test_method2(self): | ||||||
|             print ("test_method1 called") |             print("test_method1 called") | ||||||
| 
 | 
 | ||||||
|     class TestOther(object): |     class TestOther(object): | ||||||
|         @classmethod |         @classmethod | ||||||
|         def callme(cls): |         def callme(cls): | ||||||
|             print ("callme other called") |             print("callme other called") | ||||||
|         def test_other(self): |         def test_other(self): | ||||||
|             print ("test other") |             print("test other") | ||||||
| 
 | 
 | ||||||
|     # works with unittest as well ... |     # works with unittest as well ... | ||||||
|     import unittest |     import unittest | ||||||
|  | @ -52,10 +52,10 @@ will be called ahead of running any tests:: | ||||||
|     class SomeTest(unittest.TestCase): |     class SomeTest(unittest.TestCase): | ||||||
|         @classmethod |         @classmethod | ||||||
|         def callme(self): |         def callme(self): | ||||||
|             print ("SomeTest callme called") |             print("SomeTest callme called") | ||||||
| 
 | 
 | ||||||
|         def test_unit1(self): |         def test_unit1(self): | ||||||
|             print ("test_unit1 method called") |             print("test_unit1 method called") | ||||||
| 
 | 
 | ||||||
| If you run this without output capturing:: | If you run this without output capturing:: | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -70,7 +70,7 @@ marked ``smtp_connection`` fixture function.  Running the test looks like this:: | ||||||
| 
 | 
 | ||||||
|     $ pytest test_smtpsimple.py |     $ pytest test_smtpsimple.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 |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 1 item |     collected 1 item | ||||||
| 
 | 
 | ||||||
|  | @ -208,7 +208,7 @@ inspect what is going on and can now run the tests:: | ||||||
| 
 | 
 | ||||||
|     $ pytest test_module.py |     $ pytest 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 |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 2 items |     collected 2 items | ||||||
| 
 | 
 | ||||||
|  | @ -460,7 +460,7 @@ read an optional server URL from the test module which uses our fixture:: | ||||||
|         server = getattr(request.module, "smtpserver", "smtp.gmail.com") |         server = getattr(request.module, "smtpserver", "smtp.gmail.com") | ||||||
|         smtp_connection = smtplib.SMTP(server, 587, timeout=5) |         smtp_connection = smtplib.SMTP(server, 587, timeout=5) | ||||||
|         yield smtp_connection |         yield smtp_connection | ||||||
|         print ("finalizing %s (%s)" % (smtp_connection, server)) |         print("finalizing %s (%s)" % (smtp_connection, server)) | ||||||
|         smtp_connection.close() |         smtp_connection.close() | ||||||
| 
 | 
 | ||||||
| We use the ``request.module`` attribute to optionally obtain an | We use the ``request.module`` attribute to optionally obtain an | ||||||
|  | @ -690,7 +690,7 @@ Running the above tests results in the following test IDs being used:: | ||||||
| 
 | 
 | ||||||
|    $ pytest --collect-only |    $ pytest --collect-only | ||||||
|    =========================== test session starts ============================ |    =========================== test session starts ============================ | ||||||
|    platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y |    platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|    rootdir: $REGENDOC_TMPDIR, inifile: |    rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|    collected 10 items |    collected 10 items | ||||||
|    <Module 'test_anothersmtp.py'> |    <Module 'test_anothersmtp.py'> | ||||||
|  | @ -732,7 +732,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-4.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 | ||||||
|     cachedir: .pytest_cache |     cachedir: .pytest_cache | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collecting ... collected 3 items |     collecting ... collected 3 items | ||||||
|  | @ -775,7 +775,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-4.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 | ||||||
|     cachedir: .pytest_cache |     cachedir: .pytest_cache | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collecting ... collected 2 items |     collecting ... collected 2 items | ||||||
|  | @ -821,30 +821,30 @@ to show the setup/teardown flow:: | ||||||
|     @pytest.fixture(scope="module", params=["mod1", "mod2"]) |     @pytest.fixture(scope="module", params=["mod1", "mod2"]) | ||||||
|     def modarg(request): |     def modarg(request): | ||||||
|         param = request.param |         param = request.param | ||||||
|         print ("  SETUP modarg %s" % param) |         print("  SETUP modarg %s" % param) | ||||||
|         yield param |         yield param | ||||||
|         print ("  TEARDOWN modarg %s" % param) |         print("  TEARDOWN modarg %s" % param) | ||||||
| 
 | 
 | ||||||
|     @pytest.fixture(scope="function", params=[1,2]) |     @pytest.fixture(scope="function", params=[1,2]) | ||||||
|     def otherarg(request): |     def otherarg(request): | ||||||
|         param = request.param |         param = request.param | ||||||
|         print ("  SETUP otherarg %s" % param) |         print("  SETUP otherarg %s" % param) | ||||||
|         yield param |         yield param | ||||||
|         print ("  TEARDOWN otherarg %s" % param) |         print("  TEARDOWN otherarg %s" % param) | ||||||
| 
 | 
 | ||||||
|     def test_0(otherarg): |     def test_0(otherarg): | ||||||
|         print ("  RUN test0 with otherarg %s" % otherarg) |         print("  RUN test0 with otherarg %s" % otherarg) | ||||||
|     def test_1(modarg): |     def test_1(modarg): | ||||||
|         print ("  RUN test1 with modarg %s" % modarg) |         print("  RUN test1 with modarg %s" % modarg) | ||||||
|     def test_2(otherarg, modarg): |     def test_2(otherarg, modarg): | ||||||
|         print ("  RUN test2 with otherarg %s and modarg %s" % (otherarg, modarg)) |         print("  RUN test2 with otherarg %s and modarg %s" % (otherarg, modarg)) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| Let's run the tests in verbose mode and with looking at the print-output:: | 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-4.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 | ||||||
|     cachedir: .pytest_cache |     cachedir: .pytest_cache | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collecting ... collected 8 items |     collecting ... collected 8 items | ||||||
|  |  | ||||||
|  | @ -26,9 +26,9 @@ a per-session Database object:: | ||||||
|     # content of conftest.py |     # content of conftest.py | ||||||
|     class Database(object): |     class Database(object): | ||||||
|         def __init__(self): |         def __init__(self): | ||||||
|             print ("database instance created") |             print("database instance created") | ||||||
|         def destroy(self): |         def destroy(self): | ||||||
|             print ("database instance destroyed") |             print("database instance destroyed") | ||||||
| 
 | 
 | ||||||
|     def pytest_funcarg__db(request): |     def pytest_funcarg__db(request): | ||||||
|         return request.cached_setup(setup=DataBase, |         return request.cached_setup(setup=DataBase, | ||||||
|  |  | ||||||
|  | @ -27,7 +27,7 @@ Install ``pytest`` | ||||||
| 2. Check that you installed the correct version:: | 2. Check that you installed the correct version:: | ||||||
| 
 | 
 | ||||||
|     $ pytest --version |     $ pytest --version | ||||||
|     This is pytest version 3.x.y, imported from $PYTHON_PREFIX/lib/python3.6/site-packages/pytest.py |     This is pytest version 4.x.y, imported from $PYTHON_PREFIX/lib/python3.6/site-packages/pytest.py | ||||||
| 
 | 
 | ||||||
| .. _`simpletest`: | .. _`simpletest`: | ||||||
| 
 | 
 | ||||||
|  | @ -47,7 +47,7 @@ That’s it. You can now execute the test function:: | ||||||
| 
 | 
 | ||||||
|     $ pytest |     $ pytest | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 1 item |     collected 1 item | ||||||
| 
 | 
 | ||||||
|  | @ -138,7 +138,7 @@ Request a unique temporary directory for functional tests | ||||||
| 
 | 
 | ||||||
|     # content of test_tmpdir.py |     # content of test_tmpdir.py | ||||||
|     def test_needsfiles(tmpdir): |     def test_needsfiles(tmpdir): | ||||||
|         print (tmpdir) |         print(tmpdir) | ||||||
|         assert 0 |         assert 0 | ||||||
| 
 | 
 | ||||||
| List the name ``tmpdir`` in the test function signature and ``pytest`` will lookup and call a fixture factory to create the resource before performing the test function call. Before the test runs, ``pytest`` creates a unique-per-test-invocation temporary directory:: | List the name ``tmpdir`` in the test function signature and ``pytest`` will lookup and call a fixture factory to create the resource before performing the test function call. Before the test runs, ``pytest`` creates a unique-per-test-invocation temporary directory:: | ||||||
|  | @ -151,7 +151,7 @@ List the name ``tmpdir`` in the test function signature and ``pytest`` will look | ||||||
|     tmpdir = local('PYTEST_TMPDIR/test_needsfiles0') |     tmpdir = local('PYTEST_TMPDIR/test_needsfiles0') | ||||||
| 
 | 
 | ||||||
|         def test_needsfiles(tmpdir): |         def test_needsfiles(tmpdir): | ||||||
|             print (tmpdir) |             print(tmpdir) | ||||||
|     >       assert 0 |     >       assert 0 | ||||||
|     E       assert 0 |     E       assert 0 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -26,7 +26,7 @@ To execute it:: | ||||||
| 
 | 
 | ||||||
|     $ pytest |     $ pytest | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 1 item |     collected 1 item | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -54,7 +54,7 @@ them in turn:: | ||||||
| 
 | 
 | ||||||
|     $ pytest |     $ pytest | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 3 items |     collected 3 items | ||||||
| 
 | 
 | ||||||
|  | @ -103,7 +103,7 @@ Let's run this:: | ||||||
| 
 | 
 | ||||||
|     $ pytest |     $ pytest | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 3 items |     collected 3 items | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -327,7 +327,7 @@ Running it with the report-on-xfail option gives this output:: | ||||||
| 
 | 
 | ||||||
|     example $ pytest -rx xfail_demo.py |     example $ pytest -rx xfail_demo.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 |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR/example, inifile: |     rootdir: $REGENDOC_TMPDIR/example, inifile: | ||||||
|     collected 7 items |     collected 7 items | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -39,7 +39,7 @@ Running this would result in a passed test except for the last | ||||||
| 
 | 
 | ||||||
|     $ pytest test_tmp_path.py |     $ pytest test_tmp_path.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 |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 1 item |     collected 1 item | ||||||
| 
 | 
 | ||||||
|  | @ -99,7 +99,7 @@ Running this would result in a passed test except for the last | ||||||
| 
 | 
 | ||||||
|     $ pytest test_tmpdir.py |     $ pytest test_tmpdir.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 |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 1 item |     collected 1 item | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -126,7 +126,7 @@ the ``self.db`` values in the traceback:: | ||||||
| 
 | 
 | ||||||
|     $ pytest test_unittest_db.py |     $ pytest test_unittest_db.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 |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 2 items |     collected 2 items | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -154,7 +154,7 @@ Example:: | ||||||
| 
 | 
 | ||||||
|     $ pytest -ra |     $ pytest -ra | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 0 items |     collected 0 items | ||||||
| 
 | 
 | ||||||
|  | @ -177,7 +177,7 @@ More than one character can be used, so for example to only see failed and skipp | ||||||
| 
 | 
 | ||||||
|     $ pytest -rfs |     $ pytest -rfs | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 0 items |     collected 0 items | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -22,7 +22,7 @@ Running pytest now produces this output:: | ||||||
| 
 | 
 | ||||||
|     $ pytest test_show_warnings.py |     $ pytest test_show_warnings.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 |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: |     rootdir: $REGENDOC_TMPDIR, inifile: | ||||||
|     collected 1 item |     collected 1 item | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -73,7 +73,7 @@ sub directory but not for other directories:: | ||||||
|     a/conftest.py: |     a/conftest.py: | ||||||
|         def pytest_runtest_setup(item): |         def pytest_runtest_setup(item): | ||||||
|             # called for running each test in 'a' directory |             # called for running each test in 'a' directory | ||||||
|             print ("setting up", item) |             print("setting up", item) | ||||||
| 
 | 
 | ||||||
|     a/test_sub.py: |     a/test_sub.py: | ||||||
|         def test_sub(): |         def test_sub(): | ||||||
|  | @ -411,7 +411,7 @@ additionally it is possible to copy examples for an example folder before runnin | ||||||
| 
 | 
 | ||||||
|     $ pytest |     $ pytest | ||||||
|     =========================== test session starts ============================ |     =========================== test session starts ============================ | ||||||
|     platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y |     platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y | ||||||
|     rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini |     rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini | ||||||
|     collected 2 items |     collected 2 items | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -65,9 +65,9 @@ def report(issues): | ||||||
|         print(title) |         print(title) | ||||||
|         # print() |         # print() | ||||||
|         # lines = body.split("\n") |         # lines = body.split("\n") | ||||||
|         # print ("\n".join(lines[:3])) |         # print("\n".join(lines[:3])) | ||||||
|         # if len(lines) > 3 or len(body) > 240: |         # if len(lines) > 3 or len(body) > 240: | ||||||
|         #    print ("...") |         #    print("...") | ||||||
|     print("\n\nFound %s open issues" % len(issues)) |     print("\n\nFound %s open issues" % len(issues)) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -270,6 +270,7 @@ class AssertionRewritingHook(object): | ||||||
|         _issue_config_warning( |         _issue_config_warning( | ||||||
|             PytestWarning("Module already imported so cannot be rewritten: %s" % name), |             PytestWarning("Module already imported so cannot be rewritten: %s" % name), | ||||||
|             self.config, |             self.config, | ||||||
|  |             stacklevel=5, | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|     def load_module(self, name): |     def load_module(self, name): | ||||||
|  |  | ||||||
|  | @ -56,7 +56,9 @@ class Cache(object): | ||||||
|         from _pytest.warning_types import PytestWarning |         from _pytest.warning_types import PytestWarning | ||||||
| 
 | 
 | ||||||
|         _issue_config_warning( |         _issue_config_warning( | ||||||
|             PytestWarning(fmt.format(**args) if args else fmt), self._config |             PytestWarning(fmt.format(**args) if args else fmt), | ||||||
|  |             self._config, | ||||||
|  |             stacklevel=3, | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|     def makedir(self, name): |     def makedir(self, name): | ||||||
|  | @ -108,6 +110,10 @@ class Cache(object): | ||||||
|         """ |         """ | ||||||
|         path = self._getvaluepath(key) |         path = self._getvaluepath(key) | ||||||
|         try: |         try: | ||||||
|  |             if path.parent.is_dir(): | ||||||
|  |                 cache_dir_exists_already = True | ||||||
|  |             else: | ||||||
|  |                 cache_dir_exists_already = self._cachedir.exists() | ||||||
|             path.parent.mkdir(exist_ok=True, parents=True) |             path.parent.mkdir(exist_ok=True, parents=True) | ||||||
|         except (IOError, OSError): |         except (IOError, OSError): | ||||||
|             self.warn("could not create cache path {path}", path=path) |             self.warn("could not create cache path {path}", path=path) | ||||||
|  | @ -119,6 +125,7 @@ class Cache(object): | ||||||
|         else: |         else: | ||||||
|             with f: |             with f: | ||||||
|                 json.dump(value, f, indent=2, sort_keys=True) |                 json.dump(value, f, indent=2, sort_keys=True) | ||||||
|  |             if not cache_dir_exists_already: | ||||||
|                 self._ensure_supporting_files() |                 self._ensure_supporting_files() | ||||||
| 
 | 
 | ||||||
|     def _ensure_supporting_files(self): |     def _ensure_supporting_files(self): | ||||||
|  | @ -128,8 +135,10 @@ class Cache(object): | ||||||
|             if not readme_path.is_file(): |             if not readme_path.is_file(): | ||||||
|                 readme_path.write_text(README_CONTENT) |                 readme_path.write_text(README_CONTENT) | ||||||
| 
 | 
 | ||||||
|             msg = u"# created by pytest automatically, do not change\n*" |             gitignore_path = self._cachedir.joinpath(".gitignore") | ||||||
|             self._cachedir.joinpath(".gitignore").write_text(msg, encoding="UTF-8") |             if not gitignore_path.is_file(): | ||||||
|  |                 msg = u"# Created by pytest automatically.\n*" | ||||||
|  |                 gitignore_path.write_text(msg, encoding="UTF-8") | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class LFPlugin(object): | class LFPlugin(object): | ||||||
|  |  | ||||||
|  | @ -11,10 +11,10 @@ import shlex | ||||||
| import sys | import sys | ||||||
| import types | import types | ||||||
| import warnings | import warnings | ||||||
| from distutils.version import LooseVersion |  | ||||||
| 
 | 
 | ||||||
| import py | import py | ||||||
| import six | import six | ||||||
|  | from pkg_resources import parse_version | ||||||
| from pluggy import HookimplMarker | from pluggy import HookimplMarker | ||||||
| from pluggy import HookspecMarker | from pluggy import HookspecMarker | ||||||
| from pluggy import PluginManager | from pluggy import PluginManager | ||||||
|  | @ -191,7 +191,7 @@ def _prepareconfig(args=None, plugins=None): | ||||||
|         if warning: |         if warning: | ||||||
|             from _pytest.warnings import _issue_config_warning |             from _pytest.warnings import _issue_config_warning | ||||||
| 
 | 
 | ||||||
|             _issue_config_warning(warning, config=config) |             _issue_config_warning(warning, config=config, stacklevel=4) | ||||||
|         return pluginmanager.hook.pytest_cmdline_parse( |         return pluginmanager.hook.pytest_cmdline_parse( | ||||||
|             pluginmanager=pluginmanager, args=args |             pluginmanager=pluginmanager, args=args | ||||||
|         ) |         ) | ||||||
|  | @ -815,7 +815,7 @@ class Config(object): | ||||||
| 
 | 
 | ||||||
|         minver = self.inicfg.get("minversion", None) |         minver = self.inicfg.get("minversion", None) | ||||||
|         if minver: |         if minver: | ||||||
|             if LooseVersion(minver) > LooseVersion(pytest.__version__): |             if parse_version(minver) > parse_version(pytest.__version__): | ||||||
|                 raise pytest.UsageError( |                 raise pytest.UsageError( | ||||||
|                     "%s:%d: requires pytest-%s, actual pytest-%s'" |                     "%s:%d: requires pytest-%s, actual pytest-%s'" | ||||||
|                     % ( |                     % ( | ||||||
|  |  | ||||||
|  | @ -42,6 +42,7 @@ def getcfg(args, config=None): | ||||||
|                                     CFG_PYTEST_SECTION.format(filename=inibasename) |                                     CFG_PYTEST_SECTION.format(filename=inibasename) | ||||||
|                                 ), |                                 ), | ||||||
|                                 config=config, |                                 config=config, | ||||||
|  |                                 stacklevel=2, | ||||||
|                             ) |                             ) | ||||||
|                         return base, p, iniconfig["pytest"] |                         return base, p, iniconfig["pytest"] | ||||||
|                     if ( |                     if ( | ||||||
|  | @ -116,7 +117,9 @@ def determine_setup(inifile, args, rootdir_cmd_arg=None, config=None): | ||||||
|                     # TODO: [pytest] section in *.cfg files is deprecated. Need refactoring once |                     # TODO: [pytest] section in *.cfg files is deprecated. Need refactoring once | ||||||
|                     # the deprecation expires. |                     # the deprecation expires. | ||||||
|                     _issue_config_warning( |                     _issue_config_warning( | ||||||
|                         CFG_PYTEST_SECTION.format(filename=str(inifile)), config |                         CFG_PYTEST_SECTION.format(filename=str(inifile)), | ||||||
|  |                         config, | ||||||
|  |                         stacklevel=2, | ||||||
|                     ) |                     ) | ||||||
|                 break |                 break | ||||||
|             except KeyError: |             except KeyError: | ||||||
|  |  | ||||||
|  | @ -13,8 +13,9 @@ import six | ||||||
| 
 | 
 | ||||||
| import pytest | import pytest | ||||||
| from _pytest.fixtures import fixture | from _pytest.fixtures import fixture | ||||||
|  | from _pytest.pathlib import Path | ||||||
| 
 | 
 | ||||||
| RE_IMPORT_ERROR_NAME = re.compile("^No module named (.*)$") | RE_IMPORT_ERROR_NAME = re.compile(r"^No module named (.*)$") | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @fixture | @fixture | ||||||
|  | @ -267,6 +268,9 @@ class MonkeyPatch(object): | ||||||
|             self._cwd = os.getcwd() |             self._cwd = os.getcwd() | ||||||
|         if hasattr(path, "chdir"): |         if hasattr(path, "chdir"): | ||||||
|             path.chdir() |             path.chdir() | ||||||
|  |         elif isinstance(path, Path): | ||||||
|  |             # modern python uses the fspath protocol here LEGACY | ||||||
|  |             os.chdir(str(path)) | ||||||
|         else: |         else: | ||||||
|             os.chdir(path) |             os.chdir(path) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -36,7 +36,7 @@ def pytest_configure(config): | ||||||
|         from _pytest.deprecated import RESULT_LOG |         from _pytest.deprecated import RESULT_LOG | ||||||
|         from _pytest.warnings import _issue_config_warning |         from _pytest.warnings import _issue_config_warning | ||||||
| 
 | 
 | ||||||
|         _issue_config_warning(RESULT_LOG, config) |         _issue_config_warning(RESULT_LOG, config, stacklevel=2) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def pytest_unconfigure(config): | def pytest_unconfigure(config): | ||||||
|  |  | ||||||
|  | @ -647,9 +647,11 @@ class TerminalReporter(object): | ||||||
|     def pytest_terminal_summary(self): |     def pytest_terminal_summary(self): | ||||||
|         self.summary_errors() |         self.summary_errors() | ||||||
|         self.summary_failures() |         self.summary_failures() | ||||||
|         yield |  | ||||||
|         self.summary_warnings() |         self.summary_warnings() | ||||||
|  |         yield | ||||||
|         self.summary_passes() |         self.summary_passes() | ||||||
|  |         # Display any extra warnings from teardown here (if any). | ||||||
|  |         self.summary_warnings() | ||||||
| 
 | 
 | ||||||
|     def pytest_keyboard_interrupt(self, excinfo): |     def pytest_keyboard_interrupt(self, excinfo): | ||||||
|         self._keyboardinterrupt_memo = excinfo.getrepr(funcargs=True) |         self._keyboardinterrupt_memo = excinfo.getrepr(funcargs=True) | ||||||
|  | @ -726,11 +728,21 @@ class TerminalReporter(object): | ||||||
|             if not all_warnings: |             if not all_warnings: | ||||||
|                 return |                 return | ||||||
| 
 | 
 | ||||||
|  |             final = hasattr(self, "_already_displayed_warnings") | ||||||
|  |             if final: | ||||||
|  |                 warnings = all_warnings[self._already_displayed_warnings :] | ||||||
|  |             else: | ||||||
|  |                 warnings = all_warnings | ||||||
|  |             self._already_displayed_warnings = len(warnings) | ||||||
|  |             if not warnings: | ||||||
|  |                 return | ||||||
|  | 
 | ||||||
|             grouped = itertools.groupby( |             grouped = itertools.groupby( | ||||||
|                 all_warnings, key=lambda wr: wr.get_location(self.config) |                 warnings, key=lambda wr: wr.get_location(self.config) | ||||||
|             ) |             ) | ||||||
| 
 | 
 | ||||||
|             self.write_sep("=", "warnings summary", yellow=True, bold=False) |             title = "warnings summary (final)" if final else "warnings summary" | ||||||
|  |             self.write_sep("=", title, yellow=True, bold=False) | ||||||
|             for location, warning_records in grouped: |             for location, warning_records in grouped: | ||||||
|                 # legacy warnings show their location explicitly, while standard warnings look better without |                 # legacy warnings show their location explicitly, while standard warnings look better without | ||||||
|                 # it because the location is already formatted into the message |                 # it because the location is already formatted into the message | ||||||
|  | @ -786,8 +798,7 @@ class TerminalReporter(object): | ||||||
|                     self.write_line(line) |                     self.write_line(line) | ||||||
|                 else: |                 else: | ||||||
|                     msg = self._getfailureheadline(rep) |                     msg = self._getfailureheadline(rep) | ||||||
|                     markup = {"red": True, "bold": True} |                     self.write_sep("_", msg, red=True, bold=True) | ||||||
|                     self.write_sep("_", msg, **markup) |  | ||||||
|                     self._outrep_summary(rep) |                     self._outrep_summary(rep) | ||||||
|                     for report in self.getreports(""): |                     for report in self.getreports(""): | ||||||
|                         if report.nodeid == rep.nodeid and report.when == "teardown": |                         if report.nodeid == rep.nodeid and report.when == "teardown": | ||||||
|  | @ -808,7 +819,7 @@ class TerminalReporter(object): | ||||||
|                     msg = "ERROR at setup of " + msg |                     msg = "ERROR at setup of " + msg | ||||||
|                 elif rep.when == "teardown": |                 elif rep.when == "teardown": | ||||||
|                     msg = "ERROR at teardown of " + msg |                     msg = "ERROR at teardown of " + msg | ||||||
|                 self.write_sep("_", msg) |                 self.write_sep("_", msg, red=True, bold=True) | ||||||
|                 self._outrep_summary(rep) |                 self._outrep_summary(rep) | ||||||
| 
 | 
 | ||||||
|     def _outrep_summary(self, rep): |     def _outrep_summary(self, rep): | ||||||
|  |  | ||||||
|  | @ -10,6 +10,7 @@ import warnings | ||||||
| 
 | 
 | ||||||
| import attr | import attr | ||||||
| import py | import py | ||||||
|  | import six | ||||||
| 
 | 
 | ||||||
| import pytest | import pytest | ||||||
| from .pathlib import ensure_reset_dir | from .pathlib import ensure_reset_dir | ||||||
|  | @ -26,7 +27,14 @@ class TempPathFactory(object): | ||||||
| 
 | 
 | ||||||
|     The base directory can be configured using the ``--basetemp`` option.""" |     The base directory can be configured using the ``--basetemp`` option.""" | ||||||
| 
 | 
 | ||||||
|     _given_basetemp = attr.ib() |     _given_basetemp = attr.ib( | ||||||
|  |         # using os.path.abspath() to get absolute path instead of resolve() as it | ||||||
|  |         # does not work the same in all platforms (see #4427) | ||||||
|  |         # Path.absolute() exists, but it is not public (see https://bugs.python.org/issue25012) | ||||||
|  |         convert=attr.converters.optional( | ||||||
|  |             lambda p: Path(os.path.abspath(six.text_type(p))) | ||||||
|  |         ) | ||||||
|  |     ) | ||||||
|     _trace = attr.ib() |     _trace = attr.ib() | ||||||
|     _basetemp = attr.ib(default=None) |     _basetemp = attr.ib(default=None) | ||||||
| 
 | 
 | ||||||
|  | @ -53,7 +61,7 @@ class TempPathFactory(object): | ||||||
|         """ return base temporary directory. """ |         """ return base temporary directory. """ | ||||||
|         if self._basetemp is None: |         if self._basetemp is None: | ||||||
|             if self._given_basetemp is not None: |             if self._given_basetemp is not None: | ||||||
|                 basetemp = Path(self._given_basetemp) |                 basetemp = self._given_basetemp | ||||||
|                 ensure_reset_dir(basetemp) |                 ensure_reset_dir(basetemp) | ||||||
|             else: |             else: | ||||||
|                 from_env = os.environ.get("PYTEST_DEBUG_TEMPROOT") |                 from_env = os.environ.get("PYTEST_DEBUG_TEMPROOT") | ||||||
|  |  | ||||||
|  | @ -160,7 +160,7 @@ def pytest_terminal_summary(terminalreporter): | ||||||
|         yield |         yield | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def _issue_config_warning(warning, config): | def _issue_config_warning(warning, config, stacklevel): | ||||||
|     """ |     """ | ||||||
|     This function should be used instead of calling ``warnings.warn`` directly when we are in the "configure" stage: |     This function should be used instead of calling ``warnings.warn`` directly when we are in the "configure" stage: | ||||||
|     at this point the actual options might not have been set, so we manually trigger the pytest_warning_captured |     at this point the actual options might not have been set, so we manually trigger the pytest_warning_captured | ||||||
|  | @ -168,10 +168,11 @@ def _issue_config_warning(warning, config): | ||||||
| 
 | 
 | ||||||
|     :param warning: the warning instance. |     :param warning: the warning instance. | ||||||
|     :param config: |     :param config: | ||||||
|  |     :param stacklevel: stacklevel forwarded to warnings.warn | ||||||
|     """ |     """ | ||||||
|     with warnings.catch_warnings(record=True) as records: |     with warnings.catch_warnings(record=True) as records: | ||||||
|         warnings.simplefilter("always", type(warning)) |         warnings.simplefilter("always", type(warning)) | ||||||
|         warnings.warn(warning, stacklevel=2) |         warnings.warn(warning, stacklevel=stacklevel) | ||||||
|     config.hook.pytest_warning_captured.call_historic( |     config.hook.pytest_warning_captured.call_historic( | ||||||
|         kwargs=dict(warning_message=records[0], when="config", item=None) |         kwargs=dict(warning_message=records[0], when="config", item=None) | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|  | @ -206,7 +206,7 @@ class TestGeneralUsage(object): | ||||||
|         testdir.makeconftest( |         testdir.makeconftest( | ||||||
|             """ |             """ | ||||||
|             import sys |             import sys | ||||||
|             print ("should not be seen") |             print("should not be seen") | ||||||
|             sys.stderr.write("stder42\\n") |             sys.stderr.write("stder42\\n") | ||||||
|         """ |         """ | ||||||
|         ) |         ) | ||||||
|  | @ -218,7 +218,7 @@ class TestGeneralUsage(object): | ||||||
|     def test_conftest_printing_shows_if_error(self, testdir): |     def test_conftest_printing_shows_if_error(self, testdir): | ||||||
|         testdir.makeconftest( |         testdir.makeconftest( | ||||||
|             """ |             """ | ||||||
|             print ("should be seen") |             print("should be seen") | ||||||
|             assert 0 |             assert 0 | ||||||
|         """ |         """ | ||||||
|         ) |         ) | ||||||
|  | @ -301,7 +301,7 @@ class TestGeneralUsage(object): | ||||||
|             def pytest_generate_tests(metafunc): |             def pytest_generate_tests(metafunc): | ||||||
|                 metafunc.addcall({'x': 3}, id='hello-123') |                 metafunc.addcall({'x': 3}, id='hello-123') | ||||||
|             def pytest_runtest_setup(item): |             def pytest_runtest_setup(item): | ||||||
|                 print (item.keywords) |                 print(item.keywords) | ||||||
|                 if 'hello-123' in item.keywords: |                 if 'hello-123' in item.keywords: | ||||||
|                     pytest.skip("hello") |                     pytest.skip("hello") | ||||||
|                 assert 0 |                 assert 0 | ||||||
|  |  | ||||||
|  | @ -1495,7 +1495,7 @@ class TestFixtureManagerParseFactories(object): | ||||||
|                     return "class" |                     return "class" | ||||||
|                 def test_hello(self, item, fm): |                 def test_hello(self, item, fm): | ||||||
|                     faclist = fm.getfixturedefs("hello", item.nodeid) |                     faclist = fm.getfixturedefs("hello", item.nodeid) | ||||||
|                     print (faclist) |                     print(faclist) | ||||||
|                     assert len(faclist) == 3 |                     assert len(faclist) == 3 | ||||||
| 
 | 
 | ||||||
|                     assert faclist[0].func(item._request) == "conftest" |                     assert faclist[0].func(item._request) == "conftest" | ||||||
|  | @ -2040,7 +2040,7 @@ class TestAutouseManagement(object): | ||||||
|                     values.append("step2-%d" % item) |                     values.append("step2-%d" % item) | ||||||
| 
 | 
 | ||||||
|             def test_finish(): |             def test_finish(): | ||||||
|                 print (values) |                 print(values) | ||||||
|                 assert values == ["setup-1", "step1-1", "step2-1", "teardown-1", |                 assert values == ["setup-1", "step1-1", "step2-1", "teardown-1", | ||||||
|                              "setup-2", "step1-2", "step2-2", "teardown-2",] |                              "setup-2", "step1-2", "step2-2", "teardown-2",] | ||||||
|         """ |         """ | ||||||
|  | @ -2880,7 +2880,7 @@ class TestFixtureMarker(object): | ||||||
|             def base(request, fix1): |             def base(request, fix1): | ||||||
|                 def cleanup_base(): |                 def cleanup_base(): | ||||||
|                     values.append("fin_base") |                     values.append("fin_base") | ||||||
|                     print ("finalizing base") |                     print("finalizing base") | ||||||
|                 request.addfinalizer(cleanup_base) |                 request.addfinalizer(cleanup_base) | ||||||
| 
 | 
 | ||||||
|             def test_begin(): |             def test_begin(): | ||||||
|  | @ -3480,13 +3480,13 @@ class TestContextManagerFixtureFuncs(object): | ||||||
|             from test_context import fixture |             from test_context import fixture | ||||||
|             @fixture |             @fixture | ||||||
|             def arg1(): |             def arg1(): | ||||||
|                 print ("setup") |                 print("setup") | ||||||
|                 yield 1 |                 yield 1 | ||||||
|                 print ("teardown") |                 print("teardown") | ||||||
|             def test_1(arg1): |             def test_1(arg1): | ||||||
|                 print ("test1", arg1) |                 print("test1", arg1) | ||||||
|             def test_2(arg1): |             def test_2(arg1): | ||||||
|                 print ("test2", arg1) |                 print("test2", arg1) | ||||||
|                 assert 0 |                 assert 0 | ||||||
|         """ |         """ | ||||||
|         ) |         ) | ||||||
|  | @ -3509,13 +3509,13 @@ class TestContextManagerFixtureFuncs(object): | ||||||
|             from test_context import fixture |             from test_context import fixture | ||||||
|             @fixture(scope="module") |             @fixture(scope="module") | ||||||
|             def arg1(): |             def arg1(): | ||||||
|                 print ("setup") |                 print("setup") | ||||||
|                 yield 1 |                 yield 1 | ||||||
|                 print ("teardown") |                 print("teardown") | ||||||
|             def test_1(arg1): |             def test_1(arg1): | ||||||
|                 print ("test1", arg1) |                 print("test1", arg1) | ||||||
|             def test_2(arg1): |             def test_2(arg1): | ||||||
|                 print ("test2", arg1) |                 print("test2", arg1) | ||||||
|         """ |         """ | ||||||
|         ) |         ) | ||||||
|         result = testdir.runpytest("-s") |         result = testdir.runpytest("-s") | ||||||
|  |  | ||||||
|  | @ -283,7 +283,7 @@ class TestReRunTests(object): | ||||||
|                 global count, req |                 global count, req | ||||||
|                 assert request != req |                 assert request != req | ||||||
|                 req = request |                 req = request | ||||||
|                 print ("fix count %s" % count) |                 print("fix count %s" % count) | ||||||
|                 count += 1 |                 count += 1 | ||||||
|             def test_fix(fix): |             def test_fix(fix): | ||||||
|                 pass |                 pass | ||||||
|  |  | ||||||
|  | @ -33,6 +33,23 @@ class TestRaises(object): | ||||||
|         except pytest.raises.Exception: |         except pytest.raises.Exception: | ||||||
|             pass |             pass | ||||||
| 
 | 
 | ||||||
|  |     def test_raises_repr_inflight(self): | ||||||
|  |         """Ensure repr() on an exception info inside a pytest.raises with block works (#4386)""" | ||||||
|  | 
 | ||||||
|  |         class E(Exception): | ||||||
|  |             pass | ||||||
|  | 
 | ||||||
|  |         with pytest.raises(E) as excinfo: | ||||||
|  |             # this test prints the inflight uninitialized object | ||||||
|  |             # using repr and str as well as pprint to demonstrate | ||||||
|  |             # it works | ||||||
|  |             print(str(excinfo)) | ||||||
|  |             print(repr(excinfo)) | ||||||
|  |             import pprint | ||||||
|  | 
 | ||||||
|  |             pprint.pprint(excinfo) | ||||||
|  |             raise E() | ||||||
|  | 
 | ||||||
|     def test_raises_as_contextmanager(self, testdir): |     def test_raises_as_contextmanager(self, testdir): | ||||||
|         testdir.makepyfile( |         testdir.makepyfile( | ||||||
|             """ |             """ | ||||||
|  | @ -43,7 +60,7 @@ class TestRaises(object): | ||||||
|                 with pytest.raises(ZeroDivisionError) as excinfo: |                 with pytest.raises(ZeroDivisionError) as excinfo: | ||||||
|                     assert isinstance(excinfo, _pytest._code.ExceptionInfo) |                     assert isinstance(excinfo, _pytest._code.ExceptionInfo) | ||||||
|                     1/0 |                     1/0 | ||||||
|                 print (excinfo) |                 print(excinfo) | ||||||
|                 assert excinfo.type == ZeroDivisionError |                 assert excinfo.type == ZeroDivisionError | ||||||
|                 assert isinstance(excinfo.value, ZeroDivisionError) |                 assert isinstance(excinfo.value, ZeroDivisionError) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -899,5 +899,29 @@ def test_gitignore(testdir): | ||||||
|     config = testdir.parseconfig() |     config = testdir.parseconfig() | ||||||
|     cache = Cache.for_config(config) |     cache = Cache.for_config(config) | ||||||
|     cache.set("foo", "bar") |     cache.set("foo", "bar") | ||||||
|     msg = "# created by pytest automatically, do not change\n*" |     msg = "# Created by pytest automatically.\n*" | ||||||
|     assert cache._cachedir.joinpath(".gitignore").read_text(encoding="UTF-8") == msg |     gitignore_path = cache._cachedir.joinpath(".gitignore") | ||||||
|  |     assert gitignore_path.read_text(encoding="UTF-8") == msg | ||||||
|  | 
 | ||||||
|  |     # Does not overwrite existing/custom one. | ||||||
|  |     gitignore_path.write_text(u"custom") | ||||||
|  |     cache.set("something", "else") | ||||||
|  |     assert gitignore_path.read_text(encoding="UTF-8") == "custom" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def test_does_not_create_boilerplate_in_existing_dirs(testdir): | ||||||
|  |     from _pytest.cacheprovider import Cache | ||||||
|  | 
 | ||||||
|  |     testdir.makeini( | ||||||
|  |         """ | ||||||
|  |         [pytest] | ||||||
|  |         cache_dir = . | ||||||
|  |         """ | ||||||
|  |     ) | ||||||
|  |     config = testdir.parseconfig() | ||||||
|  |     cache = Cache.for_config(config) | ||||||
|  |     cache.set("foo", "bar") | ||||||
|  | 
 | ||||||
|  |     assert os.path.isdir("v")  # cache contents | ||||||
|  |     assert not os.path.exists(".gitignore") | ||||||
|  |     assert not os.path.exists("README.md") | ||||||
|  |  | ||||||
|  | @ -107,8 +107,8 @@ def test_capturing_unicode(testdir, method): | ||||||
|         # taken from issue 227 from nosetests |         # taken from issue 227 from nosetests | ||||||
|         def test_unicode(): |         def test_unicode(): | ||||||
|             import sys |             import sys | ||||||
|             print (sys.stdout) |             print(sys.stdout) | ||||||
|             print (%s) |             print(%s) | ||||||
|     """ |     """ | ||||||
|         % obj |         % obj | ||||||
|     ) |     ) | ||||||
|  | @ -121,7 +121,7 @@ def test_capturing_bytes_in_utf8_encoding(testdir, method): | ||||||
|     testdir.makepyfile( |     testdir.makepyfile( | ||||||
|         """ |         """ | ||||||
|         def test_unicode(): |         def test_unicode(): | ||||||
|             print ('b\\u00f6y') |             print('b\\u00f6y') | ||||||
|     """ |     """ | ||||||
|     ) |     ) | ||||||
|     result = testdir.runpytest("--capture=%s" % method) |     result = testdir.runpytest("--capture=%s" % method) | ||||||
|  | @ -131,7 +131,7 @@ def test_capturing_bytes_in_utf8_encoding(testdir, method): | ||||||
| def test_collect_capturing(testdir): | def test_collect_capturing(testdir): | ||||||
|     p = testdir.makepyfile( |     p = testdir.makepyfile( | ||||||
|         """ |         """ | ||||||
|         print ("collect %s failure" % 13) |         print("collect %s failure" % 13) | ||||||
|         import xyz42123 |         import xyz42123 | ||||||
|     """ |     """ | ||||||
|     ) |     ) | ||||||
|  | @ -144,14 +144,14 @@ class TestPerTestCapturing(object): | ||||||
|         p = testdir.makepyfile( |         p = testdir.makepyfile( | ||||||
|             """ |             """ | ||||||
|             def setup_module(mod): |             def setup_module(mod): | ||||||
|                 print ("setup module") |                 print("setup module") | ||||||
|             def setup_function(function): |             def setup_function(function): | ||||||
|                 print ("setup " + function.__name__) |                 print("setup " + function.__name__) | ||||||
|             def test_func1(): |             def test_func1(): | ||||||
|                 print ("in func1") |                 print("in func1") | ||||||
|                 assert 0 |                 assert 0 | ||||||
|             def test_func2(): |             def test_func2(): | ||||||
|                 print ("in func2") |                 print("in func2") | ||||||
|                 assert 0 |                 assert 0 | ||||||
|         """ |         """ | ||||||
|         ) |         ) | ||||||
|  | @ -172,14 +172,14 @@ class TestPerTestCapturing(object): | ||||||
|             """ |             """ | ||||||
|             import sys |             import sys | ||||||
|             def setup_module(func): |             def setup_module(func): | ||||||
|                 print ("module-setup") |                 print("module-setup") | ||||||
|             def setup_function(func): |             def setup_function(func): | ||||||
|                 print ("function-setup") |                 print("function-setup") | ||||||
|             def test_func(): |             def test_func(): | ||||||
|                 print ("in function") |                 print("in function") | ||||||
|                 assert 0 |                 assert 0 | ||||||
|             def teardown_function(func): |             def teardown_function(func): | ||||||
|                 print ("in teardown") |                 print("in teardown") | ||||||
|         """ |         """ | ||||||
|         ) |         ) | ||||||
|         result = testdir.runpytest(p) |         result = testdir.runpytest(p) | ||||||
|  | @ -198,9 +198,9 @@ class TestPerTestCapturing(object): | ||||||
|         p = testdir.makepyfile( |         p = testdir.makepyfile( | ||||||
|             """ |             """ | ||||||
|             def test_func1(): |             def test_func1(): | ||||||
|                 print ("in func1") |                 print("in func1") | ||||||
|             def test_func2(): |             def test_func2(): | ||||||
|                 print ("in func2") |                 print("in func2") | ||||||
|                 assert 0 |                 assert 0 | ||||||
|         """ |         """ | ||||||
|         ) |         ) | ||||||
|  | @ -213,12 +213,12 @@ class TestPerTestCapturing(object): | ||||||
|         p = testdir.makepyfile( |         p = testdir.makepyfile( | ||||||
|             """ |             """ | ||||||
|             def setup_function(function): |             def setup_function(function): | ||||||
|                 print ("setup func1") |                 print("setup func1") | ||||||
|             def teardown_function(function): |             def teardown_function(function): | ||||||
|                 print ("teardown func1") |                 print("teardown func1") | ||||||
|                 assert 0 |                 assert 0 | ||||||
|             def test_func1(): |             def test_func1(): | ||||||
|                 print ("in func1") |                 print("in func1") | ||||||
|                 pass |                 pass | ||||||
|         """ |         """ | ||||||
|         ) |         ) | ||||||
|  | @ -238,7 +238,7 @@ class TestPerTestCapturing(object): | ||||||
|         p = testdir.makepyfile( |         p = testdir.makepyfile( | ||||||
|             """ |             """ | ||||||
|             def teardown_module(mod): |             def teardown_module(mod): | ||||||
|                 print ("teardown module") |                 print("teardown module") | ||||||
|                 assert 0 |                 assert 0 | ||||||
|             def test_func(): |             def test_func(): | ||||||
|                 pass |                 pass | ||||||
|  | @ -259,10 +259,10 @@ class TestPerTestCapturing(object): | ||||||
|             """\ |             """\ | ||||||
|             import sys |             import sys | ||||||
|             def test_capturing(): |             def test_capturing(): | ||||||
|                 print (42) |                 print(42) | ||||||
|                 sys.stderr.write(str(23)) |                 sys.stderr.write(str(23)) | ||||||
|             def test_capturing_error(): |             def test_capturing_error(): | ||||||
|                 print (1) |                 print(1) | ||||||
|                 sys.stderr.write(str(2)) |                 sys.stderr.write(str(2)) | ||||||
|                 raise ValueError |                 raise ValueError | ||||||
|             """ |             """ | ||||||
|  | @ -392,7 +392,7 @@ class TestCaptureFixture(object): | ||||||
|         reprec = testdir.inline_runsource( |         reprec = testdir.inline_runsource( | ||||||
|             """\ |             """\ | ||||||
|             def test_hello(capsys): |             def test_hello(capsys): | ||||||
|                 print (42) |                 print(42) | ||||||
|                 out, err = capsys.readouterr() |                 out, err = capsys.readouterr() | ||||||
|                 assert out.startswith("42") |                 assert out.startswith("42") | ||||||
|             """, |             """, | ||||||
|  | @ -460,7 +460,7 @@ class TestCaptureFixture(object): | ||||||
|         p = testdir.makepyfile( |         p = testdir.makepyfile( | ||||||
|             """\ |             """\ | ||||||
|             def test_hello(cap{}): |             def test_hello(cap{}): | ||||||
|                 print ("xxx42xxx") |                 print("xxx42xxx") | ||||||
|                 assert 0 |                 assert 0 | ||||||
|             """.format( |             """.format( | ||||||
|                 method |                 method | ||||||
|  | @ -702,7 +702,7 @@ def test_capture_conftest_runtest_setup(testdir): | ||||||
|     testdir.makeconftest( |     testdir.makeconftest( | ||||||
|         """ |         """ | ||||||
|         def pytest_runtest_setup(): |         def pytest_runtest_setup(): | ||||||
|             print ("hello19") |             print("hello19") | ||||||
|     """ |     """ | ||||||
|     ) |     ) | ||||||
|     testdir.makepyfile("def test_func(): pass") |     testdir.makepyfile("def test_func(): pass") | ||||||
|  | @ -737,7 +737,7 @@ def test_capture_early_option_parsing(testdir): | ||||||
|     testdir.makeconftest( |     testdir.makeconftest( | ||||||
|         """ |         """ | ||||||
|         def pytest_runtest_setup(): |         def pytest_runtest_setup(): | ||||||
|             print ("hello19") |             print("hello19") | ||||||
|     """ |     """ | ||||||
|     ) |     ) | ||||||
|     testdir.makepyfile("def test_func(): pass") |     testdir.makepyfile("def test_func(): pass") | ||||||
|  | @ -1302,14 +1302,14 @@ def test_capturing_and_logging_fundamentals(testdir, method): | ||||||
| 
 | 
 | ||||||
|         logging.warn("hello1") |         logging.warn("hello1") | ||||||
|         outerr = cap.readouterr() |         outerr = cap.readouterr() | ||||||
|         print ("suspend, captured %%s" %%(outerr,)) |         print("suspend, captured %%s" %%(outerr,)) | ||||||
|         logging.warn("hello2") |         logging.warn("hello2") | ||||||
| 
 | 
 | ||||||
|         cap.pop_outerr_to_orig() |         cap.pop_outerr_to_orig() | ||||||
|         logging.warn("hello3") |         logging.warn("hello3") | ||||||
| 
 | 
 | ||||||
|         outerr = cap.readouterr() |         outerr = cap.readouterr() | ||||||
|         print ("suspend2, captured %%s" %% (outerr,)) |         print("suspend2, captured %%s" %% (outerr,)) | ||||||
|     """ |     """ | ||||||
|         % (method,) |         % (method,) | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|  | @ -371,7 +371,7 @@ class TestPython(object): | ||||||
|             import sys |             import sys | ||||||
| 
 | 
 | ||||||
|             def test_fail(): |             def test_fail(): | ||||||
|                 print ("hello-stdout") |                 print("hello-stdout") | ||||||
|                 sys.stderr.write("hello-stderr\\n") |                 sys.stderr.write("hello-stderr\\n") | ||||||
|                 logging.info('info msg') |                 logging.info('info msg') | ||||||
|                 logging.warning('warning msg') |                 logging.warning('warning msg') | ||||||
|  | @ -589,7 +589,7 @@ class TestPython(object): | ||||||
|             """ |             """ | ||||||
|             # coding: latin1 |             # coding: latin1 | ||||||
|             def test_hello(): |             def test_hello(): | ||||||
|                 print (%r) |                 print(%r) | ||||||
|                 assert 0 |                 assert 0 | ||||||
|         """ |         """ | ||||||
|             % value |             % value | ||||||
|  |  | ||||||
|  | @ -190,7 +190,7 @@ def test_ini_markers(testdir): | ||||||
|         """ |         """ | ||||||
|         def test_markers(pytestconfig): |         def test_markers(pytestconfig): | ||||||
|             markers = pytestconfig.getini("markers") |             markers = pytestconfig.getini("markers") | ||||||
|             print (markers) |             print(markers) | ||||||
|             assert len(markers) >= 2 |             assert len(markers) >= 2 | ||||||
|             assert markers[0].startswith("a1:") |             assert markers[0].startswith("a1:") | ||||||
|             assert markers[1].startswith("a2:") |             assert markers[1].startswith("a2:") | ||||||
|  |  | ||||||
|  | @ -71,11 +71,11 @@ def test_nose_setup_func(testdir): | ||||||
| 
 | 
 | ||||||
|         @with_setup(my_setup, my_teardown) |         @with_setup(my_setup, my_teardown) | ||||||
|         def test_hello(): |         def test_hello(): | ||||||
|             print (values) |             print(values) | ||||||
|             assert values == [1] |             assert values == [1] | ||||||
| 
 | 
 | ||||||
|         def test_world(): |         def test_world(): | ||||||
|             print (values) |             print(values) | ||||||
|             assert values == [1,2] |             assert values == [1,2] | ||||||
| 
 | 
 | ||||||
|     """ |     """ | ||||||
|  | @ -95,11 +95,11 @@ def test_nose_setup_func_failure(testdir): | ||||||
| 
 | 
 | ||||||
|         @with_setup(my_setup, my_teardown) |         @with_setup(my_setup, my_teardown) | ||||||
|         def test_hello(): |         def test_hello(): | ||||||
|             print (values) |             print(values) | ||||||
|             assert values == [1] |             assert values == [1] | ||||||
| 
 | 
 | ||||||
|         def test_world(): |         def test_world(): | ||||||
|             print (values) |             print(values) | ||||||
|             assert values == [1,2] |             assert values == [1,2] | ||||||
| 
 | 
 | ||||||
|     """ |     """ | ||||||
|  | @ -147,11 +147,11 @@ def test_nose_setup_partial(testdir): | ||||||
|         my_teardown_partial = partial(my_teardown, 2) |         my_teardown_partial = partial(my_teardown, 2) | ||||||
| 
 | 
 | ||||||
|         def test_hello(): |         def test_hello(): | ||||||
|             print (values) |             print(values) | ||||||
|             assert values == [1] |             assert values == [1] | ||||||
| 
 | 
 | ||||||
|         def test_world(): |         def test_world(): | ||||||
|             print (values) |             print(values) | ||||||
|             assert values == [1,2] |             assert values == [1,2] | ||||||
| 
 | 
 | ||||||
|         test_hello.setup = my_setup_partial |         test_hello.setup = my_setup_partial | ||||||
|  | @ -202,21 +202,21 @@ def test_nose_test_generator_fixtures(testdir): | ||||||
| 
 | 
 | ||||||
|         class TestClass(object): |         class TestClass(object): | ||||||
|             def setup(self): |             def setup(self): | ||||||
|                 print ("setup called in %s" % self) |                 print("setup called in %s" % self) | ||||||
|                 self.called = ['setup'] |                 self.called = ['setup'] | ||||||
| 
 | 
 | ||||||
|             def teardown(self): |             def teardown(self): | ||||||
|                 print ("teardown called in %s" % self) |                 print("teardown called in %s" % self) | ||||||
|                 eq_(self.called, ['setup']) |                 eq_(self.called, ['setup']) | ||||||
|                 self.called.append('teardown') |                 self.called.append('teardown') | ||||||
| 
 | 
 | ||||||
|             def test(self): |             def test(self): | ||||||
|                 print ("test called in %s" % self) |                 print("test called in %s" % self) | ||||||
|                 for i in range(0, 5): |                 for i in range(0, 5): | ||||||
|                     yield self.check, i |                     yield self.check, i | ||||||
| 
 | 
 | ||||||
|             def check(self, i): |             def check(self, i): | ||||||
|                 print ("check called in %s" % self) |                 print("check called in %s" % self) | ||||||
|                 expect = ['setup'] |                 expect = ['setup'] | ||||||
|                 #for x in range(0, i): |                 #for x in range(0, i): | ||||||
|                 #    expect.append('setup') |                 #    expect.append('setup') | ||||||
|  |  | ||||||
|  | @ -202,21 +202,21 @@ def test_func_generator_setup(testdir): | ||||||
|         import sys |         import sys | ||||||
| 
 | 
 | ||||||
|         def setup_module(mod): |         def setup_module(mod): | ||||||
|             print ("setup_module") |             print("setup_module") | ||||||
|             mod.x = [] |             mod.x = [] | ||||||
| 
 | 
 | ||||||
|         def setup_function(fun): |         def setup_function(fun): | ||||||
|             print ("setup_function") |             print("setup_function") | ||||||
|             x.append(1) |             x.append(1) | ||||||
| 
 | 
 | ||||||
|         def teardown_function(fun): |         def teardown_function(fun): | ||||||
|             print ("teardown_function") |             print("teardown_function") | ||||||
|             x.pop() |             x.pop() | ||||||
| 
 | 
 | ||||||
|         def test_one(): |         def test_one(): | ||||||
|             assert x == [1] |             assert x == [1] | ||||||
|             def check(): |             def check(): | ||||||
|                 print ("check") |                 print("check") | ||||||
|                 sys.stderr.write("e\\n") |                 sys.stderr.write("e\\n") | ||||||
|                 assert x == [1] |                 assert x == [1] | ||||||
|             yield check |             yield check | ||||||
|  |  | ||||||
|  | @ -365,7 +365,7 @@ class TestFixtureReporting(object): | ||||||
|         testdir.makepyfile( |         testdir.makepyfile( | ||||||
|             """ |             """ | ||||||
|             def setup_function(function): |             def setup_function(function): | ||||||
|                 print ("setup func") |                 print("setup func") | ||||||
|                 assert 0 |                 assert 0 | ||||||
|             def test_nada(): |             def test_nada(): | ||||||
|                 pass |                 pass | ||||||
|  | @ -389,7 +389,7 @@ class TestFixtureReporting(object): | ||||||
|             def test_nada(): |             def test_nada(): | ||||||
|                 pass |                 pass | ||||||
|             def teardown_function(function): |             def teardown_function(function): | ||||||
|                 print ("teardown func") |                 print("teardown func") | ||||||
|                 assert 0 |                 assert 0 | ||||||
|         """ |         """ | ||||||
|         ) |         ) | ||||||
|  | @ -412,7 +412,7 @@ class TestFixtureReporting(object): | ||||||
|                 assert 0, "failingfunc" |                 assert 0, "failingfunc" | ||||||
| 
 | 
 | ||||||
|             def teardown_function(function): |             def teardown_function(function): | ||||||
|                 print ("teardown func") |                 print("teardown func") | ||||||
|                 assert False |                 assert False | ||||||
|         """ |         """ | ||||||
|         ) |         ) | ||||||
|  | @ -436,13 +436,13 @@ class TestFixtureReporting(object): | ||||||
|         testdir.makepyfile( |         testdir.makepyfile( | ||||||
|             """ |             """ | ||||||
|             def setup_function(function): |             def setup_function(function): | ||||||
|                 print ("setup func") |                 print("setup func") | ||||||
| 
 | 
 | ||||||
|             def test_fail(): |             def test_fail(): | ||||||
|                 assert 0, "failingfunc" |                 assert 0, "failingfunc" | ||||||
| 
 | 
 | ||||||
|             def teardown_function(function): |             def teardown_function(function): | ||||||
|                 print ("teardown func") |                 print("teardown func") | ||||||
|         """ |         """ | ||||||
|         ) |         ) | ||||||
|         result = testdir.runpytest() |         result = testdir.runpytest() | ||||||
|  | @ -854,7 +854,7 @@ class TestGenericReporting(object): | ||||||
|             def g(): |             def g(): | ||||||
|                 raise IndexError |                 raise IndexError | ||||||
|             def test_func(): |             def test_func(): | ||||||
|                 print (6*7) |                 print(6*7) | ||||||
|                 g()  # --calling-- |                 g()  # --calling-- | ||||||
|         """ |         """ | ||||||
|         ) |         ) | ||||||
|  | @ -863,9 +863,9 @@ class TestGenericReporting(object): | ||||||
|             result = testdir.runpytest("--tb=%s" % tbopt) |             result = testdir.runpytest("--tb=%s" % tbopt) | ||||||
|             s = result.stdout.str() |             s = result.stdout.str() | ||||||
|             if tbopt == "long": |             if tbopt == "long": | ||||||
|                 assert "print (6*7)" in s |                 assert "print(6*7)" in s | ||||||
|             else: |             else: | ||||||
|                 assert "print (6*7)" not in s |                 assert "print(6*7)" not in s | ||||||
|             if tbopt != "no": |             if tbopt != "no": | ||||||
|                 assert "--calling--" in s |                 assert "--calling--" in s | ||||||
|                 assert "IndexError" in s |                 assert "IndexError" in s | ||||||
|  | @ -881,7 +881,7 @@ class TestGenericReporting(object): | ||||||
|             def g(): |             def g(): | ||||||
|                 raise IndexError |                 raise IndexError | ||||||
|             def test_func1(): |             def test_func1(): | ||||||
|                 print (6*7) |                 print(6*7) | ||||||
|                 g()  # --calling-- |                 g()  # --calling-- | ||||||
|             def test_func2(): |             def test_func2(): | ||||||
|                 assert 0, "hello" |                 assert 0, "hello" | ||||||
|  | @ -1074,11 +1074,54 @@ def test_terminal_summary_warnings_are_displayed(testdir): | ||||||
|             warnings.warn(UserWarning('internal warning')) |             warnings.warn(UserWarning('internal warning')) | ||||||
|     """ |     """ | ||||||
|     ) |     ) | ||||||
|     result = testdir.runpytest() |     testdir.makepyfile( | ||||||
|  |         """ | ||||||
|  |         def test_failure(): | ||||||
|  |             import warnings | ||||||
|  |             warnings.warn("warning_from_" + "test") | ||||||
|  |             assert 0 | ||||||
|  |     """ | ||||||
|  |     ) | ||||||
|  |     result = testdir.runpytest("-ra") | ||||||
|     result.stdout.fnmatch_lines( |     result.stdout.fnmatch_lines( | ||||||
|         ["*conftest.py:3:*internal warning", "*== 1 warnings in *"] |         [ | ||||||
|  |             "*= warnings summary =*", | ||||||
|  |             "*warning_from_test*", | ||||||
|  |             "*= short test summary info =*", | ||||||
|  |             "*= warnings summary (final) =*", | ||||||
|  |             "*conftest.py:3:*internal warning", | ||||||
|  |             "*== 1 failed, 2 warnings in *", | ||||||
|  |         ] | ||||||
|     ) |     ) | ||||||
|     assert "None" not in result.stdout.str() |     assert "None" not in result.stdout.str() | ||||||
|  |     stdout = result.stdout.str() | ||||||
|  |     assert stdout.count("warning_from_test") == 1 | ||||||
|  |     assert stdout.count("=== warnings summary ") == 2 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @pytest.mark.filterwarnings("default") | ||||||
|  | def test_terminal_summary_warnings_header_once(testdir): | ||||||
|  |     testdir.makepyfile( | ||||||
|  |         """ | ||||||
|  |         def test_failure(): | ||||||
|  |             import warnings | ||||||
|  |             warnings.warn("warning_from_" + "test") | ||||||
|  |             assert 0 | ||||||
|  |     """ | ||||||
|  |     ) | ||||||
|  |     result = testdir.runpytest("-ra") | ||||||
|  |     result.stdout.fnmatch_lines( | ||||||
|  |         [ | ||||||
|  |             "*= warnings summary =*", | ||||||
|  |             "*warning_from_test*", | ||||||
|  |             "*= short test summary info =*", | ||||||
|  |             "*== 1 failed, 1 warnings in *", | ||||||
|  |         ] | ||||||
|  |     ) | ||||||
|  |     assert "None" not in result.stdout.str() | ||||||
|  |     stdout = result.stdout.str() | ||||||
|  |     assert stdout.count("warning_from_test") == 1 | ||||||
|  |     assert stdout.count("=== warnings summary ") == 1 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @pytest.mark.parametrize( | @pytest.mark.parametrize( | ||||||
|  |  | ||||||
|  | @ -4,6 +4,7 @@ from __future__ import print_function | ||||||
| 
 | 
 | ||||||
| import sys | import sys | ||||||
| 
 | 
 | ||||||
|  | import attr | ||||||
| import six | import six | ||||||
| 
 | 
 | ||||||
| import pytest | import pytest | ||||||
|  | @ -25,12 +26,29 @@ def test_ensuretemp(recwarn): | ||||||
|     assert d1.check(dir=1) |     assert d1.check(dir=1) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @attr.s | ||||||
|  | class FakeConfig(object): | ||||||
|  |     basetemp = attr.ib() | ||||||
|  |     trace = attr.ib(default=None) | ||||||
|  | 
 | ||||||
|  |     @property | ||||||
|  |     def trace(self): | ||||||
|  |         return self | ||||||
|  | 
 | ||||||
|  |     def get(self, key): | ||||||
|  |         return lambda *k: None | ||||||
|  | 
 | ||||||
|  |     @property | ||||||
|  |     def option(self): | ||||||
|  |         return self | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| class TestTempdirHandler(object): | class TestTempdirHandler(object): | ||||||
|     def test_mktemp(self, testdir): |     def test_mktemp(self, tmp_path): | ||||||
|  | 
 | ||||||
|         from _pytest.tmpdir import TempdirFactory, TempPathFactory |         from _pytest.tmpdir import TempdirFactory, TempPathFactory | ||||||
| 
 | 
 | ||||||
|         config = testdir.parseconfig() |         config = FakeConfig(tmp_path) | ||||||
|         config.option.basetemp = testdir.mkdir("hello") |  | ||||||
|         t = TempdirFactory(TempPathFactory.from_config(config)) |         t = TempdirFactory(TempPathFactory.from_config(config)) | ||||||
|         tmp = t.mktemp("world") |         tmp = t.mktemp("world") | ||||||
|         assert tmp.relto(t.getbasetemp()) == "world0" |         assert tmp.relto(t.getbasetemp()) == "world0" | ||||||
|  | @ -40,6 +58,15 @@ class TestTempdirHandler(object): | ||||||
|         assert tmp2.relto(t.getbasetemp()).startswith("this") |         assert tmp2.relto(t.getbasetemp()).startswith("this") | ||||||
|         assert tmp2 != tmp |         assert tmp2 != tmp | ||||||
| 
 | 
 | ||||||
|  |     @pytest.mark.issue(4425) | ||||||
|  |     def test_tmppath_relative_basetemp_absolute(self, tmp_path, monkeypatch): | ||||||
|  |         from _pytest.tmpdir import TempPathFactory | ||||||
|  | 
 | ||||||
|  |         monkeypatch.chdir(tmp_path) | ||||||
|  |         config = FakeConfig("hello") | ||||||
|  |         t = TempPathFactory.from_config(config) | ||||||
|  |         assert t.getbasetemp().resolve() == (tmp_path / "hello").resolve() | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| class TestConfigTmpdir(object): | class TestConfigTmpdir(object): | ||||||
|     def test_getbasetemp_custom_removes_old(self, testdir): |     def test_getbasetemp_custom_removes_old(self, testdir): | ||||||
|  |  | ||||||
|  | @ -244,7 +244,7 @@ def test_setup_failure_is_shown(testdir): | ||||||
|             def setUp(self): |             def setUp(self): | ||||||
|                 assert 0, "down1" |                 assert 0, "down1" | ||||||
|             def test_method(self): |             def test_method(self): | ||||||
|                 print ("never42") |                 print("never42") | ||||||
|                 xyz |                 xyz | ||||||
|     """ |     """ | ||||||
|     ) |     ) | ||||||
|  | @ -610,14 +610,14 @@ def test_djangolike_testcase(testdir): | ||||||
|         class DjangoLikeTestCase(TestCase): |         class DjangoLikeTestCase(TestCase): | ||||||
| 
 | 
 | ||||||
|             def setUp(self): |             def setUp(self): | ||||||
|                 print ("setUp()") |                 print("setUp()") | ||||||
| 
 | 
 | ||||||
|             def test_presetup_has_been_run(self): |             def test_presetup_has_been_run(self): | ||||||
|                 print ("test_thing()") |                 print("test_thing()") | ||||||
|                 self.assertTrue(hasattr(self, 'was_presetup')) |                 self.assertTrue(hasattr(self, 'was_presetup')) | ||||||
| 
 | 
 | ||||||
|             def tearDown(self): |             def tearDown(self): | ||||||
|                 print ("tearDown()") |                 print("tearDown()") | ||||||
| 
 | 
 | ||||||
|             def __call__(self, result=None): |             def __call__(self, result=None): | ||||||
|                 try: |                 try: | ||||||
|  | @ -639,11 +639,11 @@ def test_djangolike_testcase(testdir): | ||||||
|                     return |                     return | ||||||
| 
 | 
 | ||||||
|             def _pre_setup(self): |             def _pre_setup(self): | ||||||
|                 print ("_pre_setup()") |                 print("_pre_setup()") | ||||||
|                 self.was_presetup = True |                 self.was_presetup = True | ||||||
| 
 | 
 | ||||||
|             def _post_teardown(self): |             def _post_teardown(self): | ||||||
|                 print ("_post_teardown()") |                 print("_post_teardown()") | ||||||
|     """ |     """ | ||||||
|     ) |     ) | ||||||
|     result = testdir.runpytest("-s") |     result = testdir.runpytest("-s") | ||||||
|  |  | ||||||
|  | @ -310,7 +310,7 @@ def test_warning_captured_hook(testdir): | ||||||
|         """ |         """ | ||||||
|         from _pytest.warnings import _issue_config_warning |         from _pytest.warnings import _issue_config_warning | ||||||
|         def pytest_configure(config): |         def pytest_configure(config): | ||||||
|             _issue_config_warning(UserWarning("config warning"), config) |             _issue_config_warning(UserWarning("config warning"), config, stacklevel=2) | ||||||
|     """ |     """ | ||||||
|     ) |     ) | ||||||
|     testdir.makepyfile( |     testdir.makepyfile( | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue