Skip to content
5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,11 @@ addopts = "-r a --verbose --dist worksteal"
asyncio_default_fixture_loop_scope = "function"
asyncio_mode = "auto"
timeout = 1800
# A thread timer kills the stuck worker even when its main thread is blocked and a SIGALRM handler can never run.
timeout_method = "thread"
# pytest-timeout writes its stack dump to the xdist worker's stdout, which never reaches the console. faulthandler
# writes straight to the stderr file descriptor, so a test stuck this long leaves its stacks in the log.
faulthandler_timeout = 600
markers = [
"run_alone: marks tests that must run in isolation",
]
Expand Down
11 changes: 5 additions & 6 deletions tests/unit/_utils/test_recurring_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,17 @@ async def test_start_and_stop(function: AsyncMock, delay: timedelta) -> None:
assert rt.task.done()


@pytest.mark.run_alone
async def test_execution(function: AsyncMock, delay: timedelta) -> None:
"""The recurring task calls its function repeatedly."""
third_call_done = asyncio.Event()
function.side_effect = lambda: third_call_done.set() if function.call_count >= 3 else None
task = RecurringTask(function, delay)

task.start()
await asyncio.sleep(0.2) # Wait enough for the task to execute a few times
await asyncio.wait_for(third_call_done.wait(), timeout=5)
await task.stop()

assert isinstance(task.func, AsyncMock) # To let type checker know that the function is a mock
assert task.func.call_count >= 3

await task.stop()
assert function.call_count >= 3


async def test_execution_continues_after_exception(delay: timedelta, caplog: pytest.LogCaptureFixture) -> None:
Expand Down
7 changes: 7 additions & 0 deletions tests/unit/crawlers/_playwright/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import sys

import pytest
from playwright.async_api import async_playwright
from yarl import URL
Expand Down Expand Up @@ -65,6 +67,11 @@ async def test_infinite_scroll_no_page_without_scroll(server_url: URL) -> None:
await browser.close()


@pytest.mark.skipif(
sys.platform == 'linux' and sys.version_info < (3, 11),
reason='Hangs on Linux with Python 3.10: the pytest-asyncio backports runner can leak the fixture context '
'into the test server thread.',
)
async def test_double_call_infinite_scroll(server_url: URL) -> None:
"""Checks that calling infinite_scroll twice does not load more items the second time."""
async with async_playwright() as p:
Expand Down
6 changes: 6 additions & 0 deletions tests/unit/request_loaders/test_sitemap_request_loader.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import base64
import gzip
import sys
from contextlib import asynccontextmanager
from typing import TYPE_CHECKING, Any, cast
from unittest.mock import AsyncMock, MagicMock, patch
Expand Down Expand Up @@ -346,6 +347,11 @@ def transform_request(request_options: RequestOptions) -> RequestOptions | Reque
assert extracted_urls == get_basic_results(server_url)


@pytest.mark.skipif(
sys.platform == 'linux' and sys.version_info < (3, 11),
reason='Hangs on Linux with Python 3.10: the pytest-asyncio backports runner can leak the fixture context '
'into the test server thread.',
)
async def test_transform_request_function_with_skip(server_url: URL, http_client: HttpClient) -> None:
Comment thread
vdusek marked this conversation as resolved.
Outdated
sitemap_url = (server_url / 'sitemap.xml').with_query(
base64=encode_base64(get_basic_sitemap(url=server_url).encode())
Expand Down
Loading