From 2627a60ec2155f784db2aa8d5b2a4c079be416e7 Mon Sep 17 00:00:00 2001 From: Roman Inflianskas Date: Wed, 2 Oct 2024 14:15:13 +0300 Subject: [PATCH] tests: reorder to unpin pytest Fix: #3035 Rearrange test items so that forked tests come before normal tests within their respective modules. Swap the last forked test with the last normal test if necessary. Workaround to unpin pytest. See: https://github.com/pytest-dev/pytest/issues/9621, https://github.com/pytest-dev/pytest-forked/issues/67, and specifically: https://github.com/pytest-dev/pytest-forked/issues/67#issuecomment-1964718720 --- requirements-devenv.txt | 1 - tests/conftest.py | 39 +++++++++++++++++++++++++++++++++++++++ tox.ini | 10 ---------- 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/requirements-devenv.txt b/requirements-devenv.txt index 29d3f15ec9..5696567a14 100644 --- a/requirements-devenv.txt +++ b/requirements-devenv.txt @@ -1,5 +1,4 @@ -r requirements-linting.txt -r requirements-testing.txt mockupdb # required by `pymongo` tests that are enabled by `pymongo` from linter requirements -pytest<7.0.0 # https://github.com/pytest-dev/pytest/issues/9621; see tox.ini pytest-asyncio diff --git a/tests/conftest.py b/tests/conftest.py index 64527c1e36..ade4a6c3a6 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -2,6 +2,7 @@ import os import socket import warnings +from collections import OrderedDict from threading import Thread from contextlib import contextmanager from http.server import BaseHTTPRequestHandler, HTTPServer @@ -645,3 +646,41 @@ def __eq__(self, other): def __ne__(self, other): return not self.__eq__(other) + + +def pytest_collection_modifyitems(config, items): + """ + Rearrange test items so that forked tests come before normal tests within their respective modules. + Swap the last forked test with the last normal test if necessary. + + Workaround to unpin pytest. See: + https://github.com/pytest-dev/pytest/issues/9621, + https://github.com/pytest-dev/pytest-forked/issues/67, and specifically: + https://github.com/pytest-dev/pytest-forked/issues/67#issuecomment-1964718720 + """ + module_states = OrderedDict() + + for idx in range(len(items)): + item = items[idx] + current_module = item.module.__name__ + + if current_module not in module_states: + module_states[current_module] = {"forked": [], "normal": []} + + if "forked" in item.keywords: + module_states[current_module]["forked"].append(idx) + else: + module_states[current_module]["normal"].append(idx) + + # Swap the last forked test with the last normal test if necessary + for states in module_states.values(): + if states["forked"] and states["normal"]: + last_forked_idx = states["forked"][-1] + last_normal_idx = states["normal"][-1] + + if last_forked_idx > last_normal_idx: + # Swap the items + items[last_forked_idx], items[last_normal_idx] = ( + items[last_normal_idx], + items[last_forked_idx], + ) diff --git a/tox.ini b/tox.ini index 2f351d7e5a..7af1c7b83f 100644 --- a/tox.ini +++ b/tox.ini @@ -290,19 +290,10 @@ deps = # === Common === py3.8-common: hypothesis {py3.6,py3.7,py3.8,py3.9,py3.10,py3.11,py3.12,py3.13}-common: pytest-asyncio - # See https://github.com/pytest-dev/pytest/issues/9621 - # and https://github.com/pytest-dev/pytest-forked/issues/67 - # for justification of the upper bound on pytest - {py3.6,py3.7,py3.8,py3.9,py3.10,py3.11,py3.12}-common: pytest<7.0.0 - py3.13-common: pytest # === Gevent === {py3.6,py3.7,py3.8,py3.9,py3.10,py3.11}-gevent: gevent>=22.10.0, <22.11.0 {py3.12}-gevent: gevent - # See https://github.com/pytest-dev/pytest/issues/9621 - # and https://github.com/pytest-dev/pytest-forked/issues/67 - # for justification of the upper bound on pytest - {py3.6,py3.7,py3.8,py3.9,py3.10,py3.11,py3.12}-gevent: pytest<7.0.0 # === Integrations === @@ -372,7 +363,6 @@ deps = celery-latest: Celery celery: newrelic - celery: pytest<7 {py3.7}-celery: importlib-metadata<5.0 # Chalice