diff --git a/changelog/10060.bugfix.rst b/changelog/10060.bugfix.rst deleted file mode 100644 index c8941820e..000000000 --- a/changelog/10060.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -When running with ``--pdb``, ``TestCase.tearDown`` is no longer called for tests when the *class* has been skipped via ``unittest.skip`` or ``pytest.mark.skip``. diff --git a/changelog/10114.trivial.rst b/changelog/10114.trivial.rst deleted file mode 100644 index 42c43a1d0..000000000 --- a/changelog/10114.trivial.rst +++ /dev/null @@ -1 +0,0 @@ -Replace `atomicwrites `__ dependency on windows with `os.replace`. diff --git a/changelog/10190.bugfix.rst b/changelog/10190.bugfix.rst deleted file mode 100644 index 731d0efad..000000000 --- a/changelog/10190.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Invalid XML characters in setup or teardown error messages are now properly escaped for JUnit XML reports. diff --git a/changelog/10230.bugfix.rst b/changelog/10230.bugfix.rst deleted file mode 100644 index 6ca2b00bf..000000000 --- a/changelog/10230.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Ignore ``.py`` files created by ``pyproject.toml``-based editable builds introduced in `pip 21.3 `__. diff --git a/changelog/3396.bugfix.rst b/changelog/3396.bugfix.rst deleted file mode 100644 index aa3f278c2..000000000 --- a/changelog/3396.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Doctests now respect the ``--import-mode`` flag. diff --git a/changelog/9514.bugfix.rst b/changelog/9514.bugfix.rst deleted file mode 100644 index a940b5c72..000000000 --- a/changelog/9514.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Type-annotate ``FixtureRequest.param`` as ``Any`` as a stop gap measure until :issue:`8073` is fixed. diff --git a/changelog/9791.bugfix.rst b/changelog/9791.bugfix.rst deleted file mode 100644 index f81c87016..000000000 --- a/changelog/9791.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed a path handling code in ``rewrite.py`` that seems to work fine, but was incorrect and fails in some systems. diff --git a/changelog/9917.bugfix.rst b/changelog/9917.bugfix.rst deleted file mode 100644 index ac0616d2e..000000000 --- a/changelog/9917.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed string representation for :func:`pytest.approx` when used to compare tuples. diff --git a/changelog/9937.doc.rst b/changelog/9937.doc.rst deleted file mode 100644 index 326d20ec8..000000000 --- a/changelog/9937.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Explicit note that :fixture:`tmpdir` fixture is discouraged in favour of :fixture:`tmp_path`. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index bcc0b4566..142425cde 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-7.1.3 release-7.1.2 release-7.1.1 release-7.1.0 diff --git a/doc/en/announce/release-7.1.3.rst b/doc/en/announce/release-7.1.3.rst new file mode 100644 index 000000000..4cb1b2717 --- /dev/null +++ b/doc/en/announce/release-7.1.3.rst @@ -0,0 +1,28 @@ +pytest-7.1.3 +======================================= + +pytest 7.1.3 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/stable/changelog.html. + +Thanks to all of the contributors to this release: + +* Anthony Sottile +* Bruno Oliveira +* Gergely Kalmár +* Nipunn Koorapati +* Pax +* Sviatoslav Sydorenko +* Tim Hoffmann +* Tony Narlock +* Wolfremium +* Zach OBrien +* aizpurua23a + + +Happy testing, +The pytest Development Team diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index 77ae5a130..7e2200224 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -40,32 +40,86 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a calls, which return a ``(out, err)`` namedtuple. ``out`` and ``err`` will be ``text`` objects. - capsysbinary -- .../_pytest/capture.py:895 + Returns an instance of :class:`CaptureFixture[str] `. + + Example: + + .. code-block:: python + + def test_output(capsys): + print("hello") + captured = capsys.readouterr() + assert captured.out == "hello\n" + + capsysbinary -- .../_pytest/capture.py:906 Enable bytes capturing of writes to ``sys.stdout`` and ``sys.stderr``. The captured output is made available via ``capsysbinary.readouterr()`` method calls, which return a ``(out, err)`` namedtuple. ``out`` and ``err`` will be ``bytes`` objects. - capfd -- .../_pytest/capture.py:912 + Returns an instance of :class:`CaptureFixture[bytes] `. + + Example: + + .. code-block:: python + + def test_output(capsysbinary): + print("hello") + captured = capsysbinary.readouterr() + assert captured.out == b"hello\n" + + capfd -- .../_pytest/capture.py:934 Enable text capturing of writes to file descriptors ``1`` and ``2``. The captured output is made available via ``capfd.readouterr()`` method calls, which return a ``(out, err)`` namedtuple. ``out`` and ``err`` will be ``text`` objects. - capfdbinary -- .../_pytest/capture.py:929 + Returns an instance of :class:`CaptureFixture[str] `. + + Example: + + .. code-block:: python + + def test_system_echo(capfd): + os.system('echo "hello"') + captured = capfd.readouterr() + assert captured.out == "hello\n" + + capfdbinary -- .../_pytest/capture.py:962 Enable bytes capturing of writes to file descriptors ``1`` and ``2``. The captured output is made available via ``capfd.readouterr()`` method calls, which return a ``(out, err)`` namedtuple. ``out`` and ``err`` will be ``byte`` objects. - doctest_namespace [session scope] -- .../_pytest/doctest.py:731 + Returns an instance of :class:`CaptureFixture[bytes] `. + + Example: + + .. code-block:: python + + def test_system_echo(capfdbinary): + os.system('echo "hello"') + captured = capfdbinary.readouterr() + assert captured.out == b"hello\n" + + doctest_namespace [session scope] -- .../_pytest/doctest.py:735 Fixture that returns a :py:class:`dict` that will be injected into the namespace of doctests. - pytestconfig [session scope] -- .../_pytest/fixtures.py:1334 + Usually this fixture is used in conjunction with another ``autouse`` fixture: + + .. code-block:: python + + @pytest.fixture(autouse=True) + def add_np(doctest_namespace): + doctest_namespace["np"] = numpy + + For more details: :ref:`doctest_namespace`. + + pytestconfig [session scope] -- .../_pytest/fixtures.py:1344 Session-scoped fixture that returns the session's :class:`pytest.Config` object. @@ -117,10 +171,10 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a `pytest-xdist `__ plugin. See :issue:`7767` for details. - tmpdir_factory [session scope] -- .../_pytest/legacypath.py:295 + tmpdir_factory [session scope] -- .../_pytest/legacypath.py:302 Return a :class:`pytest.TempdirFactory` instance for the test session. - tmpdir -- .../_pytest/legacypath.py:302 + tmpdir -- .../_pytest/legacypath.py:309 Return a temporary directory path object which is unique to each test function invocation, created as a sub directory of the base temporary directory. @@ -132,6 +186,11 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a The returned object is a `legacy_path`_ object. + .. note:: + These days, it is preferred to use ``tmp_path``. + + :ref:`About the tmpdir and tmpdir_factory fixtures`. + .. _legacy_path: https://py.readthedocs.io/en/latest/path.html caplog -- .../_pytest/logging.py:487 @@ -148,21 +207,26 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a monkeypatch -- .../_pytest/monkeypatch.py:29 A convenient fixture for monkey-patching. - The fixture provides these methods to modify objects, dictionaries or - os.environ:: + The fixture provides these methods to modify objects, dictionaries, or + :data:`os.environ`: - monkeypatch.setattr(obj, name, value, raising=True) - monkeypatch.delattr(obj, name, raising=True) - monkeypatch.setitem(mapping, name, value) - monkeypatch.delitem(obj, name, raising=True) - monkeypatch.setenv(name, value, prepend=None) - monkeypatch.delenv(name, raising=True) - monkeypatch.syspath_prepend(path) - monkeypatch.chdir(path) + * :meth:`monkeypatch.setattr(obj, name, value, raising=True) ` + * :meth:`monkeypatch.delattr(obj, name, raising=True) ` + * :meth:`monkeypatch.setitem(mapping, name, value) ` + * :meth:`monkeypatch.delitem(obj, name, raising=True) ` + * :meth:`monkeypatch.setenv(name, value, prepend=None) ` + * :meth:`monkeypatch.delenv(name, raising=True) ` + * :meth:`monkeypatch.syspath_prepend(path) ` + * :meth:`monkeypatch.chdir(path) ` + * :meth:`monkeypatch.context() ` All modifications will be undone after the requesting test function or - fixture has finished. The ``raising`` parameter determines if a KeyError - or AttributeError will be raised if the set/deletion operation has no target. + fixture has finished. The ``raising`` parameter determines if a :class:`KeyError` + or :class:`AttributeError` will be raised if the set/deletion operation does not have the + specified target. + + To undo modifications done by the fixture in a contained scope, + use :meth:`context() `. recwarn -- .../_pytest/recwarn.py:29 Return a :class:`WarningsRecorder` instance that records all warnings emitted by test functions. diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 01c6d6983..de3be63f1 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -28,6 +28,47 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 7.1.3 (2022-08-26) +========================= + +Bug Fixes +--------- + +- `#10060 `_: When running with ``--pdb``, ``TestCase.tearDown`` is no longer called for tests when the *class* has been skipped via ``unittest.skip`` or ``pytest.mark.skip``. + + +- `#10190 `_: Invalid XML characters in setup or teardown error messages are now properly escaped for JUnit XML reports. + + +- `#10230 `_: Ignore ``.py`` files created by ``pyproject.toml``-based editable builds introduced in `pip 21.3 `__. + + +- `#3396 `_: Doctests now respect the ``--import-mode`` flag. + + +- `#9514 `_: Type-annotate ``FixtureRequest.param`` as ``Any`` as a stop gap measure until :issue:`8073` is fixed. + + +- `#9791 `_: Fixed a path handling code in ``rewrite.py`` that seems to work fine, but was incorrect and fails in some systems. + + +- `#9917 `_: Fixed string representation for :func:`pytest.approx` when used to compare tuples. + + + +Improved Documentation +---------------------- + +- `#9937 `_: Explicit note that :fixture:`tmpdir` fixture is discouraged in favour of :fixture:`tmp_path`. + + + +Trivial/Internal Changes +------------------------ + +- `#10114 `_: Replace `atomicwrites `__ dependency on windows with `os.replace`. + + pytest 7.1.2 (2022-04-23) ========================= diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index f7e03cc8b..ce8ce8152 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -22,7 +22,7 @@ Install ``pytest`` .. code-block:: bash $ pytest --version - pytest 7.1.2 + pytest 7.1.3 .. _`simpletest`: diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst index f5217cc55..69b5e32c9 100644 --- a/doc/en/how-to/fixtures.rst +++ b/doc/en/how-to/fixtures.rst @@ -733,6 +733,8 @@ does offer some nuances for when you're in a pinch. .. code-block:: pytest $ pytest -q test_emaillib.py + . [100%] + 1 passed in 0.12s . [100%] 1 passed in 0.12s @@ -770,12 +772,11 @@ For yield fixtures, the first teardown code to run is from the right-most fixtur $ pytest test_module.py =========================== test session starts ============================ platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y - collected 1 item - - test_module.py test_bar - .after_yield_2 - after_yield_1 + rootdir: /home/sweet/project + collected 0 items + ========================== no tests ran in 0.12s =========================== + ERROR: file or directory not found: test_module.py For finalizers, the first fixture to run is last call to `request.addfinalizer`. @@ -800,11 +801,12 @@ For finalizers, the first fixture to run is last call to `request.addfinalizer`. $ pytest test_module.py =========================== test session starts ============================ platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y - collected 1 item + rootdir: /home/sweet/project + collected 0 items + + ========================== no tests ran in 0.12s =========================== + ERROR: file or directory not found: test_module.py - test_module.py test_bar - .finalizer_1 - finalizer_2 This is so because yield fixtures use `addfinalizer` behind the scenes: when the fixture executes, `addfinalizer` registers a function that resumes the generator, which in turn calls the teardown code. @@ -860,8 +862,21 @@ wouldn't be compact anymore). .. code-block:: pytest $ pytest -q test_emaillib.py - . [100%] - 1 passed in 0.12s + + ================================== ERRORS ================================== + ____________________ ERROR collecting test_emaillib.py _____________________ + ImportError while importing test module '/home/sweet/project/test_emaillib.py'. + Hint: make sure your test modules/packages have valid Python names. + Traceback: + /opt/hostedtoolcache/Python/3.8.13/x64/lib/python3.8/importlib/__init__.py:127: in import_module + return _bootstrap._gcd_import(name[level:], package, level) + test_emaillib.py:3: in + from emaillib import Email, MailAdminClient + E ModuleNotFoundError: No module named 'emaillib' + ========================= short test summary info ========================== + ERROR test_emaillib.py + !!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!! + 1 error in 0.12s .. _`safe fixture structure`: @@ -1122,12 +1137,10 @@ again, nothing much has changed: .. code-block:: pytest $ pytest -s -q --tb=no test_module.py - FFfinalizing (smtp.gmail.com) - ========================= short test summary info ========================== - FAILED test_module.py::test_ehlo - assert 0 - FAILED test_module.py::test_noop - assert 0 - 2 failed in 0.12s + no tests ran in 0.12s + ERROR: file or directory not found: test_module.py + Let's quickly create another test module that actually sets the server URL in its module namespace: @@ -1155,7 +1168,7 @@ Running it: E AssertionError: (250, b'mail.python.org') E assert 0 ------------------------- Captured stdout teardown ------------------------- - finalizing (mail.python.org) + finalizing (mail.python.org) ========================= short test summary info ========================== FAILED test_anothersmtp.py::test_showhelo - AssertionError: (250, b'mail.... @@ -1286,63 +1299,10 @@ So let's just do another run: .. code-block:: pytest $ pytest -q test_module.py - FFFF [100%] - ================================= FAILURES ================================= - ________________________ test_ehlo[smtp.gmail.com] _________________________ - smtp_connection = + no tests ran in 0.12s + ERROR: file or directory not found: test_module.py - def test_ehlo(smtp_connection): - response, msg = smtp_connection.ehlo() - assert response == 250 - assert b"smtp.gmail.com" in msg - > assert 0 # for demo purposes - E assert 0 - - test_module.py:7: AssertionError - ________________________ test_noop[smtp.gmail.com] _________________________ - - smtp_connection = - - def test_noop(smtp_connection): - response, msg = smtp_connection.noop() - assert response == 250 - > assert 0 # for demo purposes - E assert 0 - - test_module.py:13: AssertionError - ________________________ test_ehlo[mail.python.org] ________________________ - - smtp_connection = - - def test_ehlo(smtp_connection): - response, msg = smtp_connection.ehlo() - assert response == 250 - > assert b"smtp.gmail.com" in msg - E AssertionError: assert b'smtp.gmail.com' in b'mail.python.org\nPIPELINING\nSIZE 51200000\nETRN\nSTARTTLS\nAUTH DIGEST-MD5 NTLM CRAM-MD5\nENHANCEDSTATUSCODES\n8BITMIME\nDSN\nSMTPUTF8\nCHUNKING' - - test_module.py:6: AssertionError - -------------------------- Captured stdout setup --------------------------- - finalizing - ________________________ test_noop[mail.python.org] ________________________ - - smtp_connection = - - def test_noop(smtp_connection): - response, msg = smtp_connection.noop() - assert response == 250 - > assert 0 # for demo purposes - E assert 0 - - test_module.py:13: AssertionError - ------------------------- Captured stdout teardown ------------------------- - finalizing - ========================= short test summary info ========================== - FAILED test_module.py::test_ehlo[smtp.gmail.com] - assert 0 - FAILED test_module.py::test_noop[smtp.gmail.com] - assert 0 - FAILED test_module.py::test_ehlo[mail.python.org] - AssertionError: asser... - FAILED test_module.py::test_noop[mail.python.org] - assert 0 - 4 failed in 0.12s We see that our two test functions each ran twice, against the different ``smtp_connection`` instances. Note also, that with the ``mail.python.org`` @@ -1405,25 +1365,31 @@ Running the above tests results in the following test IDs being used: =========================== test session starts ============================ platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y rootdir: /home/sweet/project - collected 11 items + collected 6 items / 1 error - - - - - - - - ======================= 11 tests collected in 0.12s ======================== + ================================== ERRORS ================================== + ____________________ ERROR collecting test_emaillib.py _____________________ + ImportError while importing test module '/home/sweet/project/test_emaillib.py'. + Hint: make sure your test modules/packages have valid Python names. + Traceback: + /opt/hostedtoolcache/Python/3.8.13/x64/lib/python3.8/importlib/__init__.py:127: in import_module + return _bootstrap._gcd_import(name[level:], package, level) + test_emaillib.py:3: in + from emaillib import Email, MailAdminClient + E ModuleNotFoundError: No module named 'emaillib' + ========================= short test summary info ========================== + ERROR test_emaillib.py + !!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!! + =================== 6 tests collected, 1 error in 0.12s ==================== .. _`fixture-parametrize-marks`: