pytest-dev / pytest-xdist

pytest plugin for distributed testing and loop-on-failures testing modes.
https://pytest-xdist.readthedocs.io
MIT License
1.44k stars 227 forks source link

3.5.0: pytest fails in `testing/acceptance_test.py::TestLoadScope::test_workqueue_ordered_by_size` unit #1068

Open kloczek opened 4 months ago

kloczek commented 4 months ago

I'm using python 3.10.14 and pytest 8.1.1. Looks like something is wrong and pytest fails in one unit.

Here is pytest output: ```console + PYTHONPATH=/home/tkloczko/rpmbuild/BUILDROOT/python-pytest-xdist-3.5.0-4.fc37.x86_64/usr/lib64/python3.10/site-packages:/home/tkloczko/rpmbuild/BUILDROOT/python-pytest-xdist-3.5.0-4.fc37.x86_64/usr/lib/python3.10/site-packages + /usr/bin/pytest -ra -m 'not network' -p no:randomly -p no:benchmark -p no:django -p no:twisted ============================= test session starts ============================== platform linux -- Python 3.10.14, pytest-8.1.1, pluggy-1.4.0 rootdir: /home/tkloczko/rpmbuild/BUILD/pytest-xdist-3.5.0 configfile: tox.ini testpaths: testing plugins: xdist-3.5.0, forked-1.6.0 collected 204 items testing/acceptance_test.py ..............s..x.......xx..............s... [ 22%] ......x....................F....................... [ 47%] testing/test_dsession.py .................x...x............ [ 63%] testing/test_looponfail.py ...........x.ss [ 71%] testing/test_newhooks.py .... [ 73%] testing/test_plugin.py ................... [ 82%] testing/test_remote.py x....x........ [ 89%] testing/test_workermanage.py ........x.......s...x. [100%] =================================== FAILURES =================================== _________________ TestLoadScope.test_workqueue_ordered_by_size _________________ self = pytester = def test_workqueue_ordered_by_size(self, pytester: pytest.Pytester) -> None: test_file = """ import pytest @pytest.mark.parametrize('i', range({})) def test(i): pass """ pytester.makepyfile(test_a=test_file.format(10), test_b=test_file.format(20)) result = pytester.runpytest("-n2", "--dist=loadscope", "-v") > assert get_workers_and_test_count_by_prefix( "test_a.py::test", result.outlines ) == {"gw1": 10} E AssertionError: assert {'gw0': 10} == {'gw1': 10} E E Left contains 1 more item: E {'gw0': 10} E Right contains 1 more item: E {'gw1': 10} E Use -v to get more diff /home/tkloczko/rpmbuild/BUILD/pytest-xdist-3.5.0/testing/acceptance_test.py:1244: AssertionError ----------------------------- Captured stdout call ----------------------------- ============================= test session starts ============================== platform linux -- Python 3.10.14, pytest-8.1.1, pluggy-1.4.0 -- /usr/bin/python3 cachedir: .pytest_cache rootdir: /tmp/pytest-of-tkloczko/pytest-273/test_workqueue_ordered_by_size0 plugins: xdist-3.5.0, forked-1.6.0 created: 2/2 workers 2 workers [30 items] scheduling tests via LoadScopeScheduling test_a.py::test[0] test_b.py::test[0] [gw1] [ 3%] PASSED test_b.py::test[0] test_b.py::test[1] [gw1] [ 6%] PASSED test_b.py::test[1] test_b.py::test[2] [gw1] [ 10%] PASSED test_b.py::test[2] test_b.py::test[3] [gw1] [ 13%] PASSED test_b.py::test[3] test_b.py::test[4] [gw1] [ 16%] PASSED test_b.py::test[4] test_b.py::test[5] [gw1] [ 20%] PASSED test_b.py::test[5] test_b.py::test[6] [gw1] [ 23%] PASSED test_b.py::test[6] test_b.py::test[7] [gw1] [ 26%] PASSED test_b.py::test[7] test_b.py::test[8] [gw1] [ 30%] PASSED test_b.py::test[8] test_b.py::test[9] [gw1] [ 33%] PASSED test_b.py::test[9] test_b.py::test[10] [gw1] [ 36%] PASSED test_b.py::test[10] test_b.py::test[11] [gw1] [ 40%] PASSED test_b.py::test[11] test_b.py::test[12] [gw1] [ 43%] PASSED test_b.py::test[12] test_b.py::test[13] [gw1] [ 46%] PASSED test_b.py::test[13] test_b.py::test[14] [gw1] [ 50%] PASSED test_b.py::test[14] test_b.py::test[15] [gw1] [ 53%] PASSED test_b.py::test[15] test_b.py::test[16] [gw1] [ 56%] PASSED test_b.py::test[16] test_b.py::test[17] [gw1] [ 60%] PASSED test_b.py::test[17] test_b.py::test[18] [gw1] [ 63%] PASSED test_b.py::test[18] test_b.py::test[19] [gw1] [ 66%] PASSED test_b.py::test[19] [gw0] [ 70%] PASSED test_a.py::test[0] test_a.py::test[1] [gw0] [ 73%] PASSED test_a.py::test[1] test_a.py::test[2] [gw0] [ 76%] PASSED test_a.py::test[2] test_a.py::test[3] [gw0] [ 80%] PASSED test_a.py::test[3] test_a.py::test[4] [gw0] [ 83%] PASSED test_a.py::test[4] test_a.py::test[5] [gw0] [ 86%] PASSED test_a.py::test[5] test_a.py::test[6] [gw0] [ 90%] PASSED test_a.py::test[6] test_a.py::test[7] [gw0] [ 93%] PASSED test_a.py::test[7] test_a.py::test[8] [gw0] [ 96%] PASSED test_a.py::test[8] test_a.py::test[9] [gw0] [100%] PASSED test_a.py::test[9] ============================== 30 passed in 0.47s ============================== ================================== XFAILURES =================================== _____________________ TestDistEach.test_simple_diffoutput ______________________ cls = func = . at 0x7fa8c839cdc0> when = 'setup' reraise = (, ) @classmethod def from_call( cls, func: Callable[[], TResult], when: Literal["collect", "setup", "call", "teardown"], reraise: Optional[ Union[Type[BaseException], Tuple[Type[BaseException], ...]] ] = None, ) -> "CallInfo[TResult]": """Call func, wrapping the result in a CallInfo. :param func: The function to call. Called without arguments. :param when: The phase in which the function is called. :param reraise: Exception or exceptions that shall propagate if raised by the function, instead of being wrapped in the CallInfo. """ excinfo = None start = timing.time() precise_start = timing.perf_counter() try: > result: Optional[TResult] = func() /usr/lib/python3.10/site-packages/_pytest/runner.py:340: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.10/site-packages/_pytest/runner.py:240: in lambda: runtest_hook(item=item, **kwds), when=when, reraise=reraise /usr/lib/python3.10/site-packages/pluggy/_hooks.py:501: in __call__ return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult) /usr/lib/python3.10/site-packages/pluggy/_manager.py:119: in _hookexec return self._inner_hookexec(hook_name, methods, kwargs, firstresult) /usr/lib/python3.10/site-packages/_pytest/unraisableexception.py:85: in pytest_runtest_setup yield from unraisable_exception_runtest_hook() /usr/lib/python3.10/site-packages/_pytest/unraisableexception.py:65: in unraisable_exception_runtest_hook yield /usr/lib/python3.10/site-packages/_pytest/logging.py:843: in pytest_runtest_setup yield from self._runtest_for(item, "setup") /usr/lib/python3.10/site-packages/_pytest/logging.py:832: in _runtest_for yield /usr/lib/python3.10/site-packages/_pytest/capture.py:878: in pytest_runtest_setup return (yield) /usr/lib/python3.10/site-packages/_pytest/threadexception.py:82: in pytest_runtest_setup yield from thread_exception_runtest_hook() /usr/lib/python3.10/site-packages/_pytest/threadexception.py:63: in thread_exception_runtest_hook yield _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ item = @hookimpl(tryfirst=True) def pytest_runtest_setup(item: Item) -> None: skipped = evaluate_skip_marks(item) if skipped: raise skip.Exception(skipped.reason, _use_item_location=True) item.stash[xfailed_key] = xfailed = evaluate_xfail_marks(item) if xfailed and not item.config.option.runxfail and not xfailed.run: > xfail("[NOTRUN] " + xfailed.reason) E _pytest.outcomes.XFailed: [NOTRUN] other python versions might not have pytest installed /usr/lib/python3.10/site-packages/_pytest/skipping.py:243: XFailed ________________________ test_terminate_on_hangingnode _________________________ pytester = @pytest.mark.xfail def test_terminate_on_hangingnode(pytester: pytest.Pytester) -> None: p = pytester.makeconftest( """ def pytest_sessionfinish(session): if session.nodeid == "my": # running on worker import time time.sleep(3) """ ) result = pytester.runpytest(p, "--dist=each", "--tx=popen//id=my") assert result.duration < 2.0 > result.stdout.fnmatch_lines(["*killed*my*"]) E Failed: nomatch: '*killed*my*' E and: '============================= test session starts ==============================' E and: 'platform linux -- Python 3.10.14, pytest-8.1.1, pluggy-1.4.0' E and: 'rootdir: /tmp/pytest-of-tkloczko/pytest-273/test_terminate_on_hangingnode0' E and: 'plugins: xdist-3.5.0, forked-1.6.0' E and: 'created: 1/1 worker' E and: '1 worker [0 items]' E and: '' E and: '' E and: '============================ no tests ran in 0.29s =============================' E remains unmatched: '*killed*my*' /home/tkloczko/rpmbuild/BUILD/pytest-xdist-3.5.0/testing/acceptance_test.py:529: Failed ----------------------------- Captured stdout call ----------------------------- ============================= test session starts ============================== platform linux -- Python 3.10.14, pytest-8.1.1, pluggy-1.4.0 rootdir: /tmp/pytest-of-tkloczko/pytest-273/test_terminate_on_hangingnode0 plugins: xdist-3.5.0, forked-1.6.0 created: 1/1 worker 1 worker [0 items] ============================ no tests ran in 0.29s ============================= ______________________________ test_session_hooks ______________________________ cls = func = . at 0x7fa8c83a37f0> when = 'setup' reraise = (, ) @classmethod def from_call( cls, func: Callable[[], TResult], when: Literal["collect", "setup", "call", "teardown"], reraise: Optional[ Union[Type[BaseException], Tuple[Type[BaseException], ...]] ] = None, ) -> "CallInfo[TResult]": """Call func, wrapping the result in a CallInfo. :param func: The function to call. Called without arguments. :param when: The phase in which the function is called. :param reraise: Exception or exceptions that shall propagate if raised by the function, instead of being wrapped in the CallInfo. """ excinfo = None start = timing.time() precise_start = timing.perf_counter() try: > result: Optional[TResult] = func() /usr/lib/python3.10/site-packages/_pytest/runner.py:340: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.10/site-packages/_pytest/runner.py:240: in lambda: runtest_hook(item=item, **kwds), when=when, reraise=reraise /usr/lib/python3.10/site-packages/pluggy/_hooks.py:501: in __call__ return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult) /usr/lib/python3.10/site-packages/pluggy/_manager.py:119: in _hookexec return self._inner_hookexec(hook_name, methods, kwargs, firstresult) /usr/lib/python3.10/site-packages/_pytest/unraisableexception.py:85: in pytest_runtest_setup yield from unraisable_exception_runtest_hook() /usr/lib/python3.10/site-packages/_pytest/unraisableexception.py:65: in unraisable_exception_runtest_hook yield /usr/lib/python3.10/site-packages/_pytest/logging.py:843: in pytest_runtest_setup yield from self._runtest_for(item, "setup") /usr/lib/python3.10/site-packages/_pytest/logging.py:832: in _runtest_for yield /usr/lib/python3.10/site-packages/_pytest/capture.py:878: in pytest_runtest_setup return (yield) /usr/lib/python3.10/site-packages/_pytest/threadexception.py:82: in pytest_runtest_setup yield from thread_exception_runtest_hook() /usr/lib/python3.10/site-packages/_pytest/threadexception.py:63: in thread_exception_runtest_hook yield _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ item = @hookimpl(tryfirst=True) def pytest_runtest_setup(item: Item) -> None: skipped = evaluate_skip_marks(item) if skipped: raise skip.Exception(skipped.reason, _use_item_location=True) item.stash[xfailed_key] = xfailed = evaluate_xfail_marks(item) if xfailed and not item.config.option.runxfail and not xfailed.run: > xfail("[NOTRUN] " + xfailed.reason) E _pytest.outcomes.XFailed: [NOTRUN] works if run outside test suite /usr/lib/python3.10/site-packages/_pytest/skipping.py:243: XFailed ______________________ TestNodeFailure.test_each_multiple ______________________ self = pytester = @pytest.mark.xfail(reason="#20: xdist race condition on node restart") def test_each_multiple(self, pytester: pytest.Pytester) -> None: f = pytester.makepyfile( """ import os def test_a(): os._exit(1) def test_b(): pass """ ) res = pytester.runpytest(f, "--dist=each", "--tx=2*popen") > res.stdout.fnmatch_lines( [ "*Replacing crashed worker*", "*Worker*crashed while running*", "*2 failed*2 passed*", ] ) E Failed: nomatch: '*Replacing crashed worker*' E and: '============================= test session starts ==============================' E and: 'platform linux -- Python 3.10.14, pytest-8.1.1, pluggy-1.4.0' E and: 'rootdir: /tmp/pytest-of-tkloczko/pytest-273/test_each_multiple0' E and: 'plugins: xdist-3.5.0, forked-1.6.0' E and: 'created: 2/2 workers' E and: '2 workers [2 items]' E and: '' E and: '[gw1] node down: Not properly terminated' E and: 'F' E and: 'replacing crashed worker gw1' E and: '[gw0] node down: Not properly terminated' E and: 'F' E and: 'replacing crashed worker gw0' E and: '..' E and: '=================================== FAILURES ===================================' E and: '____________________________ test_each_multiple.py _____________________________' E and: '[gw1] linux -- Python 3.10.14 /usr/bin/python3' E and: "worker 'gw1' crashed while running 'test_each_multiple.py::test_a'" E and: '____________________________ test_each_multiple.py _____________________________' E and: '[gw0] linux -- Python 3.10.14 /usr/bin/python3' E and: "worker 'gw0' crashed while running 'test_each_multiple.py::test_a'" E and: '=========================== short test summary info ============================' E and: 'FAILED test_each_multiple.py::test_a' E and: 'FAILED test_each_multiple.py::test_a' E and: '========================= 2 failed, 2 passed in 0.70s ==========================' E remains unmatched: '*Replacing crashed worker*' /home/tkloczko/rpmbuild/BUILD/pytest-xdist-3.5.0/testing/acceptance_test.py:971: Failed ----------------------------- Captured stdout call ----------------------------- ============================= test session starts ============================== platform linux -- Python 3.10.14, pytest-8.1.1, pluggy-1.4.0 rootdir: /tmp/pytest-of-tkloczko/pytest-273/test_each_multiple0 plugins: xdist-3.5.0, forked-1.6.0 created: 2/2 workers 2 workers [2 items] [gw1] node down: Not properly terminated F replacing crashed worker gw1 [gw0] node down: Not properly terminated F replacing crashed worker gw0 .. =================================== FAILURES =================================== ____________________________ test_each_multiple.py _____________________________ [gw1] linux -- Python 3.10.14 /usr/bin/python3 worker 'gw1' crashed while running 'test_each_multiple.py::test_a' ____________________________ test_each_multiple.py _____________________________ [gw0] linux -- Python 3.10.14 /usr/bin/python3 worker 'gw0' crashed while running 'test_each_multiple.py::test_a' =========================== short test summary info ============================ FAILED test_each_multiple.py::test_a FAILED test_each_multiple.py::test_a ========================= 2 failed, 2 passed in 0.70s ========================== _____________________ TestDistReporter.test_rsync_printing _____________________ self = pytester = linecomp = <_pytest.pytester.LineComp object at 0x7fa8c6fded10> @pytest.mark.xfail def test_rsync_printing(self, pytester: pytest.Pytester, linecomp) -> None: config = pytester.parseconfig() > from _pytest.pytest_terminal import TerminalReporter E ModuleNotFoundError: No module named '_pytest.pytest_terminal' /home/tkloczko/rpmbuild/BUILD/pytest-xdist-3.5.0/testing/test_dsession.py:445: ModuleNotFoundError _____________________________ test_pytest_issue419 _____________________________ pytester = @pytest.mark.xfail(reason="duplicate test ids not supported yet") def test_pytest_issue419(pytester: pytest.Pytester) -> None: pytester.makepyfile( """ import pytest @pytest.mark.parametrize('birth_year', [1988, 1988, ]) def test_2011_table(birth_year): pass """ ) reprec = pytester.inline_run("-n1") reprec.assertoutcome(passed=2) > assert 0 E assert 0 /home/tkloczko/rpmbuild/BUILD/pytest-xdist-3.5.0/testing/test_dsession.py:535: AssertionError ----------------------------- Captured stdout call ----------------------------- ============================= test session starts ============================== platform linux -- Python 3.10.14, pytest-8.1.1, pluggy-1.4.0 rootdir: /tmp/pytest-of-tkloczko/pytest-273/test_pytest_issue4190 plugins: xdist-3.5.0, forked-1.6.0 created: 1/1 worker 1 worker [2 items] .. [100%] ============================== 2 passed in 0.29s =============================== ________________ TestLooponFailing.test_looponfail_removed_test ________________ self = pytester = @pytest.mark.xfail(reason="broken by pytest 3.1+", strict=True) def test_looponfail_removed_test(self, pytester: pytest.Pytester) -> None: modcol = pytester.getmodulecol( textwrap.dedent( """ def test_one(): assert 0 def test_two(): assert 0 """ ) ) remotecontrol = RemoteControl(modcol.config) remotecontrol.loop_once() assert len(remotecontrol.failures) == 2 modcol.path.write_text( textwrap.dedent( """ def test_xxx(): # renamed test assert 0 def test_two(): assert 1 # pass now """ ) ) removepyc(modcol.path) remotecontrol.loop_once() > assert len(remotecontrol.failures) == 0 E AssertionError: assert 1 == 0 E + where 1 = len(['test_looponfail_removed_test.py::test_xxx']) E + where ['test_looponfail_removed_test.py::test_xxx'] = .failures /home/tkloczko/rpmbuild/BUILD/pytest-xdist-3.5.0/testing/test_looponfail.py:288: AssertionError ----------------------------- Captured stdout call ----------------------------- ============================= test session starts ============================== platform linux -- Python 3.10.14, pytest-8.1.1, pluggy-1.4.0 rootdir: /tmp/pytest-of-tkloczko/pytest-273/test_looponfail_removed_test0 plugins: xdist-3.5.0, forked-1.6.0 collected 0 items ============================ no tests ran in 0.00s ============================= ============================= test session starts ============================== platform linux -- Python 3.10.14, pytest-8.1.1, pluggy-1.4.0 rootdir: /tmp/pytest-of-tkloczko/pytest-273/test_looponfail_removed_test0 plugins: xdist-3.5.0, forked-1.6.0 collected 2 items collected 2 items test_looponfail_removed_test.py FF [100%] =================================== FAILURES =================================== ___________________________________ test_one ___________________________________ def test_one(): > assert 0 E assert 0 test_looponfail_removed_test.py:2: AssertionError ___________________________________ test_two ___________________________________ def test_two(): > assert 0 E assert 0 test_looponfail_removed_test.py:4: AssertionError =========================== short test summary info ============================ FAILED test_looponfail_removed_test.py::test_one - assert 0 FAILED test_looponfail_removed_test.py::test_two - assert 0 ============================== 2 failed in 0.02s =============================== ============================= test session starts ============================== platform linux -- Python 3.10.14, pytest-8.1.1, pluggy-1.4.0 rootdir: /tmp/pytest-of-tkloczko/pytest-273/test_looponfail_removed_test0 plugins: xdist-3.5.0, forked-1.6.0 collected 1 item collected 3 items collected 3 items test_looponfail_removed_test.py F. [100%] =================================== FAILURES =================================== ___________________________________ test_xxx ___________________________________ def test_xxx(): # renamed test > assert 0 E assert 0 test_looponfail_removed_test.py:3: AssertionError =========================== short test summary info ============================ FAILED test_looponfail_removed_test.py::test_xxx - assert 0 ========================= 1 failed, 1 passed in 0.02s ========================== ____________________________ test_remoteinitconfig _____________________________ pytester = @pytest.mark.xfail(reason="#59") def test_remoteinitconfig(pytester: pytest.Pytester) -> None: from xdist.remote import remote_initconfig config1 = pytester.parseconfig() config2 = remote_initconfig(config1.option.__dict__, config1.args) > assert config2.option.__dict__ == config1.option.__dict__ E AssertionError: assert {'assertmode'...w': None, ...} == {'assertmode'...w': None, ...} E E Omitting 94 identical items, use -vv to show E Differing items: E {'file_or_dir': ['/tmp/pytest-of-tkloczko/pytest-273/test_remoteinitconfig0']} != {'file_or_dir': []} E Use -v to get more diff /home/tkloczko/rpmbuild/BUILD/pytest-xdist-3.5.0/testing/test_remote.py:79: AssertionError _____________ TestWorkerInteractor.test_happy_run_events_converted _____________ self = pytester = worker = def test_happy_run_events_converted( self, pytester: pytest.Pytester, worker: WorkerSetup ) -> None: > pytest.xfail("implement a simple test for event production") E _pytest.outcomes.XFailed: implement a simple test for event production /home/tkloczko/rpmbuild/BUILD/pytest-xdist-3.5.0/testing/test_remote.py:187: XFailed __________________ TestNodeManager.test_rsync_roots_no_roots ___________________ cls = func = . at 0x7fa8c79131c0> when = 'setup' reraise = (, ) @classmethod def from_call( cls, func: Callable[[], TResult], when: Literal["collect", "setup", "call", "teardown"], reraise: Optional[ Union[Type[BaseException], Tuple[Type[BaseException], ...]] ] = None, ) -> "CallInfo[TResult]": """Call func, wrapping the result in a CallInfo. :param func: The function to call. Called without arguments. :param when: The phase in which the function is called. :param reraise: Exception or exceptions that shall propagate if raised by the function, instead of being wrapped in the CallInfo. """ excinfo = None start = timing.time() precise_start = timing.perf_counter() try: > result: Optional[TResult] = func() /usr/lib/python3.10/site-packages/_pytest/runner.py:340: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.10/site-packages/_pytest/runner.py:240: in lambda: runtest_hook(item=item, **kwds), when=when, reraise=reraise /usr/lib/python3.10/site-packages/pluggy/_hooks.py:501: in __call__ return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult) /usr/lib/python3.10/site-packages/pluggy/_manager.py:119: in _hookexec return self._inner_hookexec(hook_name, methods, kwargs, firstresult) /usr/lib/python3.10/site-packages/_pytest/unraisableexception.py:85: in pytest_runtest_setup yield from unraisable_exception_runtest_hook() /usr/lib/python3.10/site-packages/_pytest/unraisableexception.py:65: in unraisable_exception_runtest_hook yield /usr/lib/python3.10/site-packages/_pytest/logging.py:843: in pytest_runtest_setup yield from self._runtest_for(item, "setup") /usr/lib/python3.10/site-packages/_pytest/logging.py:832: in _runtest_for yield /usr/lib/python3.10/site-packages/_pytest/capture.py:878: in pytest_runtest_setup return (yield) /usr/lib/python3.10/site-packages/_pytest/threadexception.py:82: in pytest_runtest_setup yield from thread_exception_runtest_hook() /usr/lib/python3.10/site-packages/_pytest/threadexception.py:63: in thread_exception_runtest_hook yield _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ item = @hookimpl(tryfirst=True) def pytest_runtest_setup(item: Item) -> None: skipped = evaluate_skip_marks(item) if skipped: raise skip.Exception(skipped.reason, _use_item_location=True) item.stash[xfailed_key] = xfailed = evaluate_xfail_marks(item) if xfailed and not item.config.option.runxfail and not xfailed.run: > xfail("[NOTRUN] " + xfailed.reason) E _pytest.outcomes.XFailed: [NOTRUN] /usr/lib/python3.10/site-packages/_pytest/skipping.py:243: XFailed _____________________ test_unserialize_warning_msg[Nested] _____________________ w_cls = 'Nested' @pytest.mark.parametrize( "w_cls", [ UserWarning, MyWarning, "Imported", pytest.param( "Nested", marks=pytest.mark.xfail(reason="Nested warning classes are not supported."), ), ], ) def test_unserialize_warning_msg(w_cls): """Test that warning serialization process works well""" # Create a test warning message with pytest.warns(UserWarning) as w: if not isinstance(w_cls, str): warnings.warn("hello", w_cls) elif w_cls == "Imported": generate_warning() elif w_cls == "Nested": # dynamic creation class MyWarning2(UserWarning): pass warnings.warn("hello", MyWarning2) # Unpack assert len(w) == 1 w_msg = w[0] # Serialize and deserialize data = serialize_warning_message(w_msg) > w_msg2 = unserialize_warning_message(data) testing/test_workermanage.py:369: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ data = {'category_class_name': 'MyWarning2', 'category_module': 'test_workermanage', 'file': None, 'filename': '/home/tkloczko/rpmbuild/BUILD/pytest-xdist-3.5.0/testing/test_workermanage.py', ...} def unserialize_warning_message(data): import warnings import importlib if data["message_module"]: mod = importlib.import_module(data["message_module"]) > cls = getattr(mod, data["message_class_name"]) E AttributeError: module 'test_workermanage' has no attribute 'MyWarning2'. Did you mean: 'MyWarning'? ../../BUILDROOT/python-pytest-xdist-3.5.0-4.fc37.x86_64/usr/lib/python3.10/site-packages/xdist/workermanage.py:417: AttributeError =============================== warnings summary =============================== testing/acceptance_test.py::TestDistribution::test_n1_pass /usr/lib/python3.10/site-packages/_pytest/pathlib.py:97: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-ed36e0e7-4ba6-4a0a-bbc5-e7d421682cb2/test_safe_get_no_perms0 : [Errno 39] Directory not empty: 'test_safe_get_no_perms0' warnings.warn( testing/acceptance_test.py::TestDistribution::test_n1_pass /usr/lib/python3.10/site-packages/_pytest/pathlib.py:97: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-ed36e0e7-4ba6-4a0a-bbc5-e7d421682cb2/test_safe_set_no_perms0 : [Errno 39] Directory not empty: 'test_safe_set_no_perms0' warnings.warn( testing/acceptance_test.py::TestDistribution::test_n1_pass /usr/lib/python3.10/site-packages/_pytest/pathlib.py:97: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-ed36e0e7-4ba6-4a0a-bbc5-e7d421682cb2/test_safe_delete_no_perms0 : [Errno 39] Directory not empty: 'test_safe_delete_no_perms0' warnings.warn( testing/acceptance_test.py::TestDistribution::test_n1_pass /usr/lib/python3.10/site-packages/_pytest/pathlib.py:97: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-ed36e0e7-4ba6-4a0a-bbc5-e7d421682cb2/test_rmtree_errorhandler_rerai0 : [Errno 39] Directory not empty: 'test_rmtree_errorhandler_rerai0' warnings.warn( testing/acceptance_test.py::TestDistribution::test_n1_pass /usr/lib/python3.10/site-packages/_pytest/pathlib.py:97: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-ed36e0e7-4ba6-4a0a-bbc5-e7d421682cb2 : [Errno 39] Directory not empty: '/tmp/pytest-of-tkloczko/garbage-ed36e0e7-4ba6-4a0a-bbc5-e7d421682cb2' warnings.warn( -- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html =========================== short test summary info ============================ SKIPPED [3] ../../../../../usr/lib/python3.10/site-packages/_pytest/pytester.py:1522: could not import 'pexpect': No module named 'pexpect' SKIPPED [1] testing/acceptance_test.py:809: pytest 8.1.1 does not have the pytest_warning_captured hook. SKIPPED [1] testing/test_workermanage.py:316: no 'gspecs' option found XFAIL testing/acceptance_test.py::TestDistEach::test_simple_diffoutput - reason: [NOTRUN] other python versions might not have pytest installed XFAIL testing/acceptance_test.py::test_terminate_on_hangingnode XFAIL testing/acceptance_test.py::test_session_hooks - reason: [NOTRUN] works if run outside test suite XFAIL testing/acceptance_test.py::TestNodeFailure::test_each_multiple - #20: xdist race condition on node restart XFAIL testing/test_dsession.py::TestDistReporter::test_rsync_printing XFAIL testing/test_dsession.py::test_pytest_issue419 - duplicate test ids not supported yet XFAIL testing/test_looponfail.py::TestLooponFailing::test_looponfail_removed_test - broken by pytest 3.1+ XFAIL testing/test_remote.py::test_remoteinitconfig - #59 XFAIL testing/test_remote.py::TestWorkerInteractor::test_happy_run_events_converted - reason: implement a simple test for event production XFAIL testing/test_workermanage.py::TestNodeManager::test_rsync_roots_no_roots - reason: [NOTRUN] XFAIL testing/test_workermanage.py::test_unserialize_warning_msg[Nested] - Nested warning classes are not supported. FAILED testing/acceptance_test.py::TestLoadScope::test_workqueue_ordered_by_size = 1 failed, 187 passed, 5 skipped, 11 xfailed, 5 warnings in 65.93s (0:01:05) == ```
kloczek commented 4 months ago

Just tested 3.5.0 + all patches generated from master and looks like issue already has been resolved.

Here is pytest output: ```console + PYTHONPATH=/home/tkloczko/rpmbuild/BUILDROOT/python-pytest-xdist-3.5.0-4.fc37.x86_64/usr/lib64/python3.10/site-packages:/home/tkloczko/rpmbuild/BUILDROOT/python-pytest-xdist-3.5.0-4.fc37.x86_64/usr/lib/python3.10/site-packages + /usr/bin/pytest -ra -m 'not network' -p no:randomly -p no:benchmark -p no:django -p no:twisted ==================================================================================== test session starts ==================================================================================== platform linux -- Python 3.10.14, pytest-8.1.1, pluggy-1.4.0 rootdir: /home/tkloczko/rpmbuild/BUILD/pytest-xdist-3.5.0 configfile: tox.ini testpaths: testing plugins: xdist-3.5.0, forked-1.6.0 collected 207 items testing/acceptance_test.py ..............s..x.......xx..............s.........x............................................... [ 47%] testing/test_dsession.py .................x...x............ [ 64%] testing/test_looponfail.py ............x.ss [ 71%] testing/test_newhooks.py .... [ 73%] testing/test_plugin.py ................... [ 83%] testing/test_remote.py ....x........ [ 89%] testing/test_workermanage.py ........x.......s...x. [100%] ========================================================================================= XFAILURES ========================================================================================= ____________________________________________________________________________ TestDistEach.test_simple_diffoutput ____________________________________________________________________________ cls = , func = . at 0x7f317a98c550>, when = 'setup' reraise = (, ) @classmethod def from_call( cls, func: Callable[[], TResult], when: Literal["collect", "setup", "call", "teardown"], reraise: Optional[ Union[Type[BaseException], Tuple[Type[BaseException], ...]] ] = None, ) -> "CallInfo[TResult]": """Call func, wrapping the result in a CallInfo. :param func: The function to call. Called without arguments. :param when: The phase in which the function is called. :param reraise: Exception or exceptions that shall propagate if raised by the function, instead of being wrapped in the CallInfo. """ excinfo = None start = timing.time() precise_start = timing.perf_counter() try: > result: Optional[TResult] = func() /usr/lib/python3.10/site-packages/_pytest/runner.py:340: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.10/site-packages/_pytest/runner.py:240: in lambda: runtest_hook(item=item, **kwds), when=when, reraise=reraise /usr/lib/python3.10/site-packages/pluggy/_hooks.py:501: in __call__ return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult) /usr/lib/python3.10/site-packages/pluggy/_manager.py:119: in _hookexec return self._inner_hookexec(hook_name, methods, kwargs, firstresult) /usr/lib/python3.10/site-packages/_pytest/unraisableexception.py:85: in pytest_runtest_setup yield from unraisable_exception_runtest_hook() /usr/lib/python3.10/site-packages/_pytest/unraisableexception.py:65: in unraisable_exception_runtest_hook yield /usr/lib/python3.10/site-packages/_pytest/logging.py:843: in pytest_runtest_setup yield from self._runtest_for(item, "setup") /usr/lib/python3.10/site-packages/_pytest/logging.py:832: in _runtest_for yield /usr/lib/python3.10/site-packages/_pytest/capture.py:878: in pytest_runtest_setup return (yield) /usr/lib/python3.10/site-packages/_pytest/threadexception.py:82: in pytest_runtest_setup yield from thread_exception_runtest_hook() /usr/lib/python3.10/site-packages/_pytest/threadexception.py:63: in thread_exception_runtest_hook yield _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ item = @hookimpl(tryfirst=True) def pytest_runtest_setup(item: Item) -> None: skipped = evaluate_skip_marks(item) if skipped: raise skip.Exception(skipped.reason, _use_item_location=True) item.stash[xfailed_key] = xfailed = evaluate_xfail_marks(item) if xfailed and not item.config.option.runxfail and not xfailed.run: > xfail("[NOTRUN] " + xfailed.reason) E _pytest.outcomes.XFailed: [NOTRUN] other python versions might not have pytest installed /usr/lib/python3.10/site-packages/_pytest/skipping.py:243: XFailed _______________________________________________________________________________ test_terminate_on_hangingnode _______________________________________________________________________________ pytester = @pytest.mark.xfail def test_terminate_on_hangingnode(pytester: pytest.Pytester) -> None: p = pytester.makeconftest( """ def pytest_sessionfinish(session): if session.nodeid == "my": # running on worker import time time.sleep(3) """ ) result = pytester.runpytest(p, "--dist=each", "--tx=popen//id=my") assert result.duration < 2.0 > result.stdout.fnmatch_lines(["*killed*my*"]) E Failed: nomatch: '*killed*my*' E and: '============================= test session starts ==============================' E and: 'platform linux -- Python 3.10.14, pytest-8.1.1, pluggy-1.4.0' E and: 'rootdir: /tmp/pytest-of-tkloczko/pytest-56/test_terminate_on_hangingnode0' E and: 'plugins: xdist-3.5.0, forked-1.6.0' E and: 'created: 1/1 worker' E and: '1 worker [0 items]' E and: '' E and: '' E and: '============================ no tests ran in 0.29s =============================' E remains unmatched: '*killed*my*' /home/tkloczko/rpmbuild/BUILD/pytest-xdist-3.5.0/testing/acceptance_test.py:528: Failed ----------------------------------------------------------------------------------- Captured stdout call ------------------------------------------------------------------------------------ ============================= test session starts ============================== platform linux -- Python 3.10.14, pytest-8.1.1, pluggy-1.4.0 rootdir: /tmp/pytest-of-tkloczko/pytest-56/test_terminate_on_hangingnode0 plugins: xdist-3.5.0, forked-1.6.0 created: 1/1 worker 1 worker [0 items] ============================ no tests ran in 0.29s ============================= ____________________________________________________________________________________ test_session_hooks _____________________________________________________________________________________ cls = , func = . at 0x7f317b10f9a0>, when = 'setup' reraise = (, ) @classmethod def from_call( cls, func: Callable[[], TResult], when: Literal["collect", "setup", "call", "teardown"], reraise: Optional[ Union[Type[BaseException], Tuple[Type[BaseException], ...]] ] = None, ) -> "CallInfo[TResult]": """Call func, wrapping the result in a CallInfo. :param func: The function to call. Called without arguments. :param when: The phase in which the function is called. :param reraise: Exception or exceptions that shall propagate if raised by the function, instead of being wrapped in the CallInfo. """ excinfo = None start = timing.time() precise_start = timing.perf_counter() try: > result: Optional[TResult] = func() /usr/lib/python3.10/site-packages/_pytest/runner.py:340: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.10/site-packages/_pytest/runner.py:240: in lambda: runtest_hook(item=item, **kwds), when=when, reraise=reraise /usr/lib/python3.10/site-packages/pluggy/_hooks.py:501: in __call__ return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult) /usr/lib/python3.10/site-packages/pluggy/_manager.py:119: in _hookexec return self._inner_hookexec(hook_name, methods, kwargs, firstresult) /usr/lib/python3.10/site-packages/_pytest/unraisableexception.py:85: in pytest_runtest_setup yield from unraisable_exception_runtest_hook() /usr/lib/python3.10/site-packages/_pytest/unraisableexception.py:65: in unraisable_exception_runtest_hook yield /usr/lib/python3.10/site-packages/_pytest/logging.py:843: in pytest_runtest_setup yield from self._runtest_for(item, "setup") /usr/lib/python3.10/site-packages/_pytest/logging.py:832: in _runtest_for yield /usr/lib/python3.10/site-packages/_pytest/capture.py:878: in pytest_runtest_setup return (yield) /usr/lib/python3.10/site-packages/_pytest/threadexception.py:82: in pytest_runtest_setup yield from thread_exception_runtest_hook() /usr/lib/python3.10/site-packages/_pytest/threadexception.py:63: in thread_exception_runtest_hook yield _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ item = @hookimpl(tryfirst=True) def pytest_runtest_setup(item: Item) -> None: skipped = evaluate_skip_marks(item) if skipped: raise skip.Exception(skipped.reason, _use_item_location=True) item.stash[xfailed_key] = xfailed = evaluate_xfail_marks(item) if xfailed and not item.config.option.runxfail and not xfailed.run: > xfail("[NOTRUN] " + xfailed.reason) E _pytest.outcomes.XFailed: [NOTRUN] works if run outside test suite /usr/lib/python3.10/site-packages/_pytest/skipping.py:243: XFailed ____________________________________________________________________________ TestNodeFailure.test_each_multiple _____________________________________________________________________________ self = , pytester = @pytest.mark.xfail(reason="#20: xdist race condition on node restart") def test_each_multiple(self, pytester: pytest.Pytester) -> None: f = pytester.makepyfile( """ import os def test_a(): os._exit(1) def test_b(): pass """ ) res = pytester.runpytest(f, "--dist=each", "--tx=2*popen") > res.stdout.fnmatch_lines( [ "*Replacing crashed worker*", "*Worker*crashed while running*", "*2 failed*2 passed*", ] ) E Failed: nomatch: '*Replacing crashed worker*' E and: '============================= test session starts ==============================' E and: 'platform linux -- Python 3.10.14, pytest-8.1.1, pluggy-1.4.0' E and: 'rootdir: /tmp/pytest-of-tkloczko/pytest-56/test_each_multiple0' E and: 'plugins: xdist-3.5.0, forked-1.6.0' E and: 'created: 2/2 workers' E and: '2 workers [2 items]' E and: '' E and: '[gw0] node down: Not properly terminated' E and: 'F' E and: 'replacing crashed worker gw0' E and: '[gw1] node down: Not properly terminated' E and: 'F' E and: 'replacing crashed worker gw1' E and: '..' E and: '=================================== FAILURES ===================================' E and: '____________________________ test_each_multiple.py _____________________________' E and: '[gw0] linux -- Python 3.10.14 /usr/bin/python3' E and: "worker 'gw0' crashed while running 'test_each_multiple.py::test_a'" E and: '____________________________ test_each_multiple.py _____________________________' E and: '[gw1] linux -- Python 3.10.14 /usr/bin/python3' E and: "worker 'gw1' crashed while running 'test_each_multiple.py::test_a'" E and: '=========================== short test summary info ============================' E and: 'FAILED test_each_multiple.py::test_a' E and: 'FAILED test_each_multiple.py::test_a' E and: '========================= 2 failed, 2 passed in 0.69s ==========================' E remains unmatched: '*Replacing crashed worker*' /home/tkloczko/rpmbuild/BUILD/pytest-xdist-3.5.0/testing/acceptance_test.py:966: Failed ----------------------------------------------------------------------------------- Captured stdout call ------------------------------------------------------------------------------------ ============================= test session starts ============================== platform linux -- Python 3.10.14, pytest-8.1.1, pluggy-1.4.0 rootdir: /tmp/pytest-of-tkloczko/pytest-56/test_each_multiple0 plugins: xdist-3.5.0, forked-1.6.0 created: 2/2 workers 2 workers [2 items] [gw0] node down: Not properly terminated F replacing crashed worker gw0 [gw1] node down: Not properly terminated F replacing crashed worker gw1 .. =================================== FAILURES =================================== ____________________________ test_each_multiple.py _____________________________ [gw0] linux -- Python 3.10.14 /usr/bin/python3 worker 'gw0' crashed while running 'test_each_multiple.py::test_a' ____________________________ test_each_multiple.py _____________________________ [gw1] linux -- Python 3.10.14 /usr/bin/python3 worker 'gw1' crashed while running 'test_each_multiple.py::test_a' =========================== short test summary info ============================ FAILED test_each_multiple.py::test_a FAILED test_each_multiple.py::test_a ========================= 2 failed, 2 passed in 0.69s ========================== ___________________________________________________________________________ TestDistReporter.test_rsync_printing ____________________________________________________________________________ self = , pytester = linecomp = <_pytest.pytester.LineComp object at 0x7f317a4ecf70> @pytest.mark.xfail def test_rsync_printing(self, pytester: pytest.Pytester, linecomp) -> None: config = pytester.parseconfig() from _pytest.terminal import TerminalReporter rep = TerminalReporter(config, file=linecomp.stringio) config.pluginmanager.register(rep, "terminalreporter") dsession = DSession(config) class gw1: id = "X1" spec = execnet.XSpec("popen") class gw2: id = "X2" spec = execnet.XSpec("popen") # class rinfo: # version_info = (2, 5, 1, 'final', 0) # executable = "hello" # platform = "xyz" # cwd = "qwe" # dsession.pytest_xdist_newgateway(gw1, rinfo) # linecomp.assert_contains_lines([ # "*X1*popen*xyz*2.5*" # ]) > dsession.pytest_xdist_rsyncstart(source="hello", gateways=[gw1, gw2]) # type: ignore[attr-defined] E AttributeError: 'DSession' object has no attribute 'pytest_xdist_rsyncstart' /home/tkloczko/rpmbuild/BUILD/pytest-xdist-3.5.0/testing/test_dsession.py:469: AttributeError ___________________________________________________________________________________ test_pytest_issue419 ____________________________________________________________________________________ pytester = @pytest.mark.xfail(reason="duplicate test ids not supported yet") def test_pytest_issue419(pytester: pytest.Pytester) -> None: pytester.makepyfile( """ import pytest @pytest.mark.parametrize('birth_year', [1988, 1988, ]) def test_2011_table(birth_year): pass """ ) reprec = pytester.inline_run("-n1") reprec.assertoutcome(passed=2) > assert 0 E assert 0 /home/tkloczko/rpmbuild/BUILD/pytest-xdist-3.5.0/testing/test_dsession.py:535: AssertionError ----------------------------------------------------------------------------------- Captured stdout call ------------------------------------------------------------------------------------ ============================= test session starts ============================== platform linux -- Python 3.10.14, pytest-8.1.1, pluggy-1.4.0 rootdir: /tmp/pytest-of-tkloczko/pytest-56/test_pytest_issue4190 plugins: xdist-3.5.0, forked-1.6.0 created: 1/1 worker 1 worker [2 items] .. [100%] ============================== 2 passed in 0.30s =============================== ______________________________________________________________________ TestLooponFailing.test_looponfail_removed_test _______________________________________________________________________ self = , pytester = @pytest.mark.xfail(reason="broken by pytest 3.1+", strict=True) def test_looponfail_removed_test(self, pytester: pytest.Pytester) -> None: modcol = pytester.getmodulecol( textwrap.dedent( """ def test_one(): assert 0 def test_two(): assert 0 """ ) ) remotecontrol = RemoteControl(modcol.config) remotecontrol.loop_once() assert len(remotecontrol.failures) == 2 modcol.path.write_text( textwrap.dedent( """ def test_xxx(): # renamed test assert 0 def test_two(): assert 1 # pass now """ ) ) removepyc(modcol.path) remotecontrol.loop_once() > assert len(remotecontrol.failures) == 0 E AssertionError: assert 1 == 0 E + where 1 = len(['test_looponfail_removed_test.py::test_xxx']) E + where ['test_looponfail_removed_test.py::test_xxx'] = .failures /home/tkloczko/rpmbuild/BUILD/pytest-xdist-3.5.0/testing/test_looponfail.py:316: AssertionError ----------------------------------------------------------------------------------- Captured stdout call ------------------------------------------------------------------------------------ ============================= test session starts ============================== platform linux -- Python 3.10.14, pytest-8.1.1, pluggy-1.4.0 rootdir: /tmp/pytest-of-tkloczko/pytest-56/test_looponfail_removed_test0 plugins: xdist-3.5.0, forked-1.6.0 collected 0 items ============================ no tests ran in 0.01s ============================= ============================= test session starts ============================== platform linux -- Python 3.10.14, pytest-8.1.1, pluggy-1.4.0 rootdir: /tmp/pytest-of-tkloczko/pytest-56/test_looponfail_removed_test0 plugins: xdist-3.5.0, forked-1.6.0 collected 2 items collected 2 items test_looponfail_removed_test.py FF [100%] =================================== FAILURES =================================== ___________________________________ test_one ___________________________________ def test_one(): > assert 0 E assert 0 test_looponfail_removed_test.py:2: AssertionError ___________________________________ test_two ___________________________________ def test_two(): > assert 0 E assert 0 test_looponfail_removed_test.py:4: AssertionError =========================== short test summary info ============================ FAILED test_looponfail_removed_test.py::test_one - assert 0 FAILED test_looponfail_removed_test.py::test_two - assert 0 ============================== 2 failed in 0.03s =============================== ============================= test session starts ============================== platform linux -- Python 3.10.14, pytest-8.1.1, pluggy-1.4.0 rootdir: /tmp/pytest-of-tkloczko/pytest-56/test_looponfail_removed_test0 plugins: xdist-3.5.0, forked-1.6.0 collected 1 item collected 3 items collected 3 items test_looponfail_removed_test.py F. [100%] =================================== FAILURES =================================== ___________________________________ test_xxx ___________________________________ def test_xxx(): # renamed test > assert 0 E assert 0 test_looponfail_removed_test.py:3: AssertionError =========================== short test summary info ============================ FAILED test_looponfail_removed_test.py::test_xxx - assert 0 ========================= 1 failed, 1 passed in 0.03s ========================== ___________________________________________________________________ TestWorkerInteractor.test_happy_run_events_converted ____________________________________________________________________ self = , pytester = worker = def test_happy_run_events_converted( self, pytester: pytest.Pytester, worker: WorkerSetup ) -> None: > pytest.xfail("implement a simple test for event production") E _pytest.outcomes.XFailed: implement a simple test for event production /home/tkloczko/rpmbuild/BUILD/pytest-xdist-3.5.0/testing/test_remote.py:178: XFailed _________________________________________________________________________ TestNodeManager.test_rsync_roots_no_roots _________________________________________________________________________ cls = , func = . at 0x7f317a983f40>, when = 'setup' reraise = (, ) @classmethod def from_call( cls, func: Callable[[], TResult], when: Literal["collect", "setup", "call", "teardown"], reraise: Optional[ Union[Type[BaseException], Tuple[Type[BaseException], ...]] ] = None, ) -> "CallInfo[TResult]": """Call func, wrapping the result in a CallInfo. :param func: The function to call. Called without arguments. :param when: The phase in which the function is called. :param reraise: Exception or exceptions that shall propagate if raised by the function, instead of being wrapped in the CallInfo. """ excinfo = None start = timing.time() precise_start = timing.perf_counter() try: > result: Optional[TResult] = func() /usr/lib/python3.10/site-packages/_pytest/runner.py:340: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.10/site-packages/_pytest/runner.py:240: in lambda: runtest_hook(item=item, **kwds), when=when, reraise=reraise /usr/lib/python3.10/site-packages/pluggy/_hooks.py:501: in __call__ return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult) /usr/lib/python3.10/site-packages/pluggy/_manager.py:119: in _hookexec return self._inner_hookexec(hook_name, methods, kwargs, firstresult) /usr/lib/python3.10/site-packages/_pytest/unraisableexception.py:85: in pytest_runtest_setup yield from unraisable_exception_runtest_hook() /usr/lib/python3.10/site-packages/_pytest/unraisableexception.py:65: in unraisable_exception_runtest_hook yield /usr/lib/python3.10/site-packages/_pytest/logging.py:843: in pytest_runtest_setup yield from self._runtest_for(item, "setup") /usr/lib/python3.10/site-packages/_pytest/logging.py:832: in _runtest_for yield /usr/lib/python3.10/site-packages/_pytest/capture.py:878: in pytest_runtest_setup return (yield) /usr/lib/python3.10/site-packages/_pytest/threadexception.py:82: in pytest_runtest_setup yield from thread_exception_runtest_hook() /usr/lib/python3.10/site-packages/_pytest/threadexception.py:63: in thread_exception_runtest_hook yield _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ item = @hookimpl(tryfirst=True) def pytest_runtest_setup(item: Item) -> None: skipped = evaluate_skip_marks(item) if skipped: raise skip.Exception(skipped.reason, _use_item_location=True) item.stash[xfailed_key] = xfailed = evaluate_xfail_marks(item) if xfailed and not item.config.option.runxfail and not xfailed.run: > xfail("[NOTRUN] " + xfailed.reason) E _pytest.outcomes.XFailed: [NOTRUN] /usr/lib/python3.10/site-packages/_pytest/skipping.py:243: XFailed ___________________________________________________________________________ test_unserialize_warning_msg[Nested] ____________________________________________________________________________ w_cls = 'Nested' @pytest.mark.parametrize( "w_cls", [ UserWarning, MyWarning, "Imported", pytest.param( "Nested", marks=pytest.mark.xfail(reason="Nested warning classes are not supported."), ), ], ) def test_unserialize_warning_msg(w_cls): """Test that warning serialization process works well.""" # Create a test warning message with pytest.warns(UserWarning) as w: if not isinstance(w_cls, str): warnings.warn("hello", w_cls) elif w_cls == "Imported": generate_warning() elif w_cls == "Nested": # dynamic creation class MyWarning2(UserWarning): pass warnings.warn("hello", MyWarning2) # Unpack assert len(w) == 1 w_msg = w[0] # Serialize and deserialize data = serialize_warning_message(w_msg) > w_msg2 = unserialize_warning_message(data) testing/test_workermanage.py:373: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ data = {'category_class_name': 'MyWarning2', 'category_module': 'test_workermanage', 'file': None, 'filename': '/home/tkloczko/rpmbuild/BUILD/pytest-xdist-3.5.0/testing/test_workermanage.py', ...} def unserialize_warning_message(data): import importlib import warnings if data["message_module"]: mod = importlib.import_module(data["message_module"]) > cls = getattr(mod, data["message_class_name"]) E AttributeError: module 'test_workermanage' has no attribute 'MyWarning2'. Did you mean: 'MyWarning'? ../../BUILDROOT/python-pytest-xdist-3.5.0-4.fc37.x86_64/usr/lib/python3.10/site-packages/xdist/workermanage.py:408: AttributeError ================================================================================== short test summary info ================================================================================== SKIPPED [3] ../../../../../usr/lib/python3.10/site-packages/_pytest/pytester.py:1522: could not import 'pexpect': No module named 'pexpect' SKIPPED [1] testing/acceptance_test.py:804: pytest 8.1.1 does not have the pytest_warning_captured hook. SKIPPED [1] testing/test_workermanage.py:321: no 'gspecs' option found XFAIL testing/acceptance_test.py::TestDistEach::test_simple_diffoutput - reason: [NOTRUN] other python versions might not have pytest installed XFAIL testing/acceptance_test.py::test_terminate_on_hangingnode XFAIL testing/acceptance_test.py::test_session_hooks - reason: [NOTRUN] works if run outside test suite XFAIL testing/acceptance_test.py::TestNodeFailure::test_each_multiple - #20: xdist race condition on node restart XFAIL testing/test_dsession.py::TestDistReporter::test_rsync_printing XFAIL testing/test_dsession.py::test_pytest_issue419 - duplicate test ids not supported yet XFAIL testing/test_looponfail.py::TestLooponFailing::test_looponfail_removed_test - broken by pytest 3.1+ XFAIL testing/test_remote.py::TestWorkerInteractor::test_happy_run_events_converted - reason: implement a simple test for event production XFAIL testing/test_workermanage.py::TestNodeManager::test_rsync_roots_no_roots - reason: [NOTRUN] XFAIL testing/test_workermanage.py::test_unserialize_warning_msg[Nested] - Nested warning classes are not supported. =================================================================== 192 passed, 5 skipped, 10 xfailed in 69.91s (0:01:09) =================================================================== ```

Maybe it would be good to flush all already committed changes and release new version? 🤔