Skip to content

pytester: patch GC_COLLECT_ITERATIONS to speed up the test suite #13513

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/_pytest/pytester.py
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,13 @@ def __init__(
# Do not use colors for inner runs by default.
mp.setenv("PY_COLORS", "0")

# Pytester executes a full pytest section, including calling `pytest_unconfigure()`, which causes
# the `unraisableexception` plugin to call `gc.collect()` multiple times.
# Disable this forced garbage collection as it seriously slows down the entire test suite (#13482).
from _pytest import unraisableexception

mp.setattr(unraisableexception, "GC_COLLECT_ITERATIONS", 0)

@property
def path(self) -> Path:
"""Temporary directory path used to create files/run tests from, etc."""
Expand Down
9 changes: 6 additions & 3 deletions src/_pytest/unraisableexception.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,13 @@
from exceptiongroup import ExceptionGroup


# This constant was determined experimentally by the Trio project.
GC_COLLECT_ITERATIONS = 5


def gc_collect_harder() -> None:
# A single collection doesn't necessarily collect everything.
# Constant determined experimentally by the Trio project.
for _ in range(5):
"""Call gc.collect() multiple times, a single collection doesn't necessarily collect everything."""
for _ in range(GC_COLLECT_ITERATIONS):
gc.collect()


Expand Down
16 changes: 13 additions & 3 deletions testing/test_unraisableexception.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import sys
from unittest import mock

from _pytest import unraisableexception
from _pytest.pytester import Pytester
import pytest

Expand Down Expand Up @@ -238,7 +239,10 @@ def _disable_gc() -> Generator[None]:
_set_gc_state(enabled=was_enabled)


def test_refcycle_unraisable(pytester: Pytester) -> None:
def test_refcycle_unraisable(
pytester: Pytester, monkeypatch: pytest.MonkeyPatch
) -> None:
monkeypatch.setattr(unraisableexception, "GC_COLLECT_ITERATIONS", 5)
# see: https://github.com/pytest-dev/pytest/issues/10404
pytester.makepyfile(
test_it="""
Expand Down Expand Up @@ -267,7 +271,10 @@ def test_it():


@pytest.mark.filterwarnings("default::pytest.PytestUnraisableExceptionWarning")
def test_refcycle_unraisable_warning_filter(pytester: Pytester) -> None:
def test_refcycle_unraisable_warning_filter(
pytester: Pytester, monkeypatch: pytest.MonkeyPatch
) -> None:
monkeypatch.setattr(unraisableexception, "GC_COLLECT_ITERATIONS", 5)
# note that the host pytest warning filter is disabled and the pytester
# warning filter applies during config teardown of unraisablehook.
# see: https://github.com/pytest-dev/pytest/issues/10404
Expand Down Expand Up @@ -298,7 +305,10 @@ def test_it():


@pytest.mark.filterwarnings("default::pytest.PytestUnraisableExceptionWarning")
def test_create_task_raises_unraisable_warning_filter(pytester: Pytester) -> None:
def test_create_task_raises_unraisable_warning_filter(
pytester: Pytester, monkeypatch: pytest.MonkeyPatch
) -> None:
monkeypatch.setattr(unraisableexception, "GC_COLLECT_ITERATIONS", 5)
# note that the host pytest warning filter is disabled and the pytester
# warning filter applies during config teardown of unraisablehook.
# see: https://github.com/pytest-dev/pytest/issues/10404
Expand Down
Loading