PYTHON-4520 Add test-async tox command and automated async testing (#1699)

This commit is contained in:
Noah Stapp 2024-06-26 12:21:00 -07:00 committed by GitHub
parent 3617b5cf51
commit b035c9ce65
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 60 additions and 15 deletions

View File

@ -258,6 +258,10 @@ if [ -z "$GREEN_FRAMEWORK" ]; then
# Use --capture=tee-sys so pytest prints test output inline:
# https://docs.pytest.org/en/stable/how-to/capture-stdout-stderr.html
python -m pytest -v --capture=tee-sys --durations=5 --maxfail=10 $TEST_ARGS
if [ -z "$TEST_ARGS" ]; then # TODO: remove this in PYTHON-4528
python -m pytest -v --capture=tee-sys --durations=5 --maxfail=10 test/synchronous/ $TEST_ARGS
fi
python -m pytest -v --capture=tee-sys --durations=5 --maxfail=10 test/asynchronous/ $TEST_ARGS
else
python green_framework_test.py $GREEN_FRAMEWORK -v $TEST_ARGS
fi

View File

@ -71,6 +71,9 @@ jobs:
- name: Run tests
run: |
tox -m test
- name: Run async tests
run: |
tox -m test-async
doctest:
runs-on: ubuntu-latest
@ -203,3 +206,5 @@ jobs:
which python
pip install -e ".[test]"
pytest -v
pytest -v test/synchronous/
pytest -v test/asynchronous/

View File

@ -28,7 +28,10 @@ from pymongo.asynchronous.database import AsyncDatabase
sys.path[0:0] = [""]
from test import unittest
from test.asynchronous import AsyncIntegrationTest, async_client_context
from test.asynchronous import ( # TODO: fix sync imports in PYTHON-4528
AsyncIntegrationTest,
async_client_context,
)
from test.utils import (
IMPOSSIBLE_WRITE_CONCERN,
EventListener,
@ -472,8 +475,8 @@ class AsyncTestCollection(AsyncIntegrationTest):
async def test_index_haystack(self):
db = self.db
await db.test.drop()
_id = await db.test.insert_one(
{"pos": {"long": 34.2, "lat": 33.3}, "type": "restaurant"}
_id = (
await db.test.insert_one({"pos": {"long": 34.2, "lat": 33.3}, "type": "restaurant"})
).inserted_id
await db.test.insert_one({"pos": {"long": 34.2, "lat": 37.3}, "type": "restaurant"})
await db.test.insert_one({"pos": {"long": 59.1, "lat": 87.2}, "type": "office"})

View File

@ -1,6 +1,6 @@
from __future__ import annotations
from test.synchronous import setup, teardown
from test import setup, teardown
import pytest

View File

@ -27,8 +27,11 @@ from pymongo.synchronous.database import Database
sys.path[0:0] = [""]
from test import unittest
from test.synchronous import IntegrationTest, client_context
from test import ( # TODO: fix sync imports in PYTHON-4528
IntegrationTest,
client_context,
unittest,
)
from test.utils import (
IMPOSSIBLE_WRITE_CONCERN,
EventListener,
@ -461,8 +464,8 @@ class TestCollection(IntegrationTest):
def test_index_haystack(self):
db = self.db
db.test.drop()
_id = db.test.insert_one(
{"pos": {"long": 34.2, "lat": 33.3}, "type": "restaurant"}
_id = (
db.test.insert_one({"pos": {"long": 34.2, "lat": 33.3}, "type": "restaurant"})
).inserted_id
db.test.insert_one({"pos": {"long": 34.2, "lat": 37.3}, "type": "restaurant"})
db.test.insert_one({"pos": {"long": 59.1, "lat": 87.2}, "type": "office"})

View File

@ -92,6 +92,8 @@ docstring_replacements: dict[tuple[str, str], str] = {
type_replacements = {"_Condition": "threading.Condition"}
import_replacements = {"test.synchronous": "test"}
_pymongo_base = "./pymongo/asynchronous/"
_gridfs_base = "./gridfs/asynchronous/"
_test_base = "./test/asynchronous/"
@ -136,23 +138,31 @@ def process_files(files: list[str]) -> None:
if "__init__" not in file or "__init__" and "test" in file:
with open(file, "r+") as f:
lines = f.readlines()
lines = apply_is_sync(lines)
lines = apply_is_sync(lines, file)
lines = translate_coroutine_types(lines)
lines = translate_async_sleeps(lines)
if file in docstring_translate_files:
lines = translate_docstrings(lines)
translate_locks(lines)
translate_types(lines)
if file in sync_test_files:
translate_imports(lines)
f.seek(0)
f.writelines(lines)
f.truncate()
def apply_is_sync(lines: list[str]) -> list[str]:
is_sync = next(iter([line for line in lines if line.startswith("_IS_SYNC = ")]))
index = lines.index(is_sync)
is_sync = is_sync.replace("False", "True")
lines[index] = is_sync
def apply_is_sync(lines: list[str], file: str) -> list[str]:
try:
is_sync = next(iter([line for line in lines if line.startswith("_IS_SYNC = ")]))
index = lines.index(is_sync)
is_sync = is_sync.replace("False", "True")
lines[index] = is_sync
except StopIteration as e:
print(
f"Missing _IS_SYNC at top of async file {file.replace('synchronous', 'asynchronous')}"
)
raise e
return lines
@ -196,6 +206,15 @@ def translate_types(lines: list[str]) -> list[str]:
return lines
def translate_imports(lines: list[str]) -> list[str]:
for k, v in import_replacements.items():
matches = [line for line in lines if k in line and "import" in line]
for line in matches:
index = lines.index(line)
lines[index] = line.replace(k, v)
return lines
def translate_async_sleeps(lines: list[str]) -> list[str]:
blocking_sleeps = [line for line in lines if "asyncio.sleep(0)" in line]
lines = [line for line in lines if line not in blocking_sleeps]

View File

@ -1,4 +1,4 @@
#!/bin/bash
#!/bin/bash -eu
python ./tools/synchro.py
python -m ruff check pymongo/synchronous/ gridfs/synchronous/ test/synchronous --fix --silent

11
tox.ini
View File

@ -5,6 +5,8 @@ requires =
envlist =
# Test using the system Python.
test,
# Test async tests using the system Python.
test-async,
# Test using the run-tests Evergreen script.
test-eg,
# Set up encryption files and services.
@ -34,6 +36,7 @@ envlist =
labels = # Use labels and -m instead of -e so that tox -m <label> fails instantly if the label does not exist
test = test
test-async = test-async
test-eg = test-eg
setup-encryption = setup-encryption
teardown-encryption = teardown-encryption
@ -63,6 +66,14 @@ extras =
test
commands =
pytest -v --durations=5 --maxfail=10 {posargs}
pytest -v --durations=5 --maxfail=10 test/synchronous/ {posargs}
[testenv:test-async]
description = run base set of async unit tests with no extra functionality
extras =
test
commands =
pytest -v --durations=5 --maxfail=10 test/asynchronous/ {posargs}
[testenv:test-eg]
description = run tests using run-tests.sh Evergreen script