From 359aca759da27854dcfce4145d6fb01fdea4a426 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Sun, 14 Sep 2025 13:12:54 -0500 Subject: [PATCH 01/10] add simple uvloop tests --- .github/workflows/test-python.yml | 2 ++ tools/test_uv_loop.py | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 tools/test_uv_loop.py diff --git a/.github/workflows/test-python.yml b/.github/workflows/test-python.yml index 6499e8ba8d..e1f8ca5f28 100644 --- a/.github/workflows/test-python.yml +++ b/.github/workflows/test-python.yml @@ -75,6 +75,8 @@ jobs: version: "${{ matrix.mongodb-version }}" - name: Run tests run: uv run --extra test pytest -v + - name: Run uvloop test + run: uv run tools/test_uv_loop.py doctest: runs-on: ubuntu-latest diff --git a/tools/test_uv_loop.py b/tools/test_uv_loop.py new file mode 100644 index 0000000000..c3de93ee7a --- /dev/null +++ b/tools/test_uv_loop.py @@ -0,0 +1,26 @@ +# /// script +# dependencies = [ +# "uvloop>=0.18" +# ] +# requires-python = ">=3.11" +# /// +from __future__ import annotations + +import sys +from pathlib import Path + +import uvloop + +# Use pymongo from parent directory. +root = Path(__file__).parent.parent +sys.path.insert(0, str(root)) + +from pymongo import AsyncMongoClient # noqa: E402 + + +async def main(): + client = AsyncMongoClient() + print(await client.admin.command("ping")) + + +uvloop.run(main()) From 7f8006a1aaca7f5eb55ad3f7c81a4bde67d36ba5 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 17 Sep 2025 07:53:33 -0500 Subject: [PATCH 02/10] PYTHON-5550 Add a test that uses uvloop as the event loop --- .github/workflows/test-python.yml | 24 ++++++++++++++++++++ CONTRIBUTING.md | 6 +++++ integration_tests/README.md | 19 ++++++++++++++++ integration_tests/run.sh | 17 ++++++++++++++ {tools => integration_tests}/test_uv_loop.py | 5 ++-- justfile | 4 ++++ 6 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 integration_tests/README.md create mode 100755 integration_tests/run.sh rename {tools => integration_tests}/test_uv_loop.py (78%) diff --git a/.github/workflows/test-python.yml b/.github/workflows/test-python.yml index e1f8ca5f28..f6866af873 100644 --- a/.github/workflows/test-python.yml +++ b/.github/workflows/test-python.yml @@ -165,6 +165,30 @@ jobs: run: | just typing + integration_tets: + runs-on: ubuntu-latest + name: Integration Tests + steps: + - uses: actions/checkout@v5 + with: + persist-credentials: false + - name: Install uv + uses: astral-sh/setup-uv@557e51de59eb14aaaba2ed9621916900a91d50c6 # v5 + with: + enable-cache: true + python-version: "3.9" + - name: Install just + run: uv tool install rust-just + - id: setup-mongodb + uses: mongodb-labs/drivers-evergreen-tools@master + with: + version: "8.0" + - name: Install dependencies + run: just install + - name: Run tests + run: | + just integration-tests + make_sdist: runs-on: ubuntu-latest name: "Make an sdist" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ed52727765..5a628263c7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -413,6 +413,12 @@ a use the ticket number as the "reason" parameter to the decorator, e.g. `@flaky When running tests locally (not in CI), the `flaky` decorator will be disabled unless `ENABLE_FLAKY` is set. To disable the `flaky` decorator in CI, you can use `evergreen patch --param DISABLE_FLAKY=1`. +## Integration Tests + +The `integration_tests` directory has a set of scripts that verify the usage of PyMongo with downstream packages or frameworks. See the [README](./integration_tests/README.md) for more information. + +To run the tests, use `just integration_tests`. + ## Specification Tests The MongoDB [specifications repository](https://github.com/mongodb/specifications) diff --git a/integration_tests/README.md b/integration_tests/README.md new file mode 100644 index 0000000000..d6da378f1a --- /dev/null +++ b/integration_tests/README.md @@ -0,0 +1,19 @@ +# Integration Tests + +A set of tests that verify the usage of PyMongo with downstream packages or frameworks. + +Each test uses [PEP 723 inline metadata](https://packaging.python.org/en/latest/specifications/inline-script-metadata/) and can be run using `pipx` or `uv`. + +The `run.sh` convenience script can be used to run all of the files using `uv`. + +When creating a new script, use the following snippet to ensure that the local version of PyMongo is used: + + +```python +# Use pymongo from parent directory. +import sys +from pathlib import Path + +root = Path(__file__).parent.parent +sys.path.insert(0, str(root)) +``` diff --git a/integration_tests/run.sh b/integration_tests/run.sh new file mode 100755 index 0000000000..eb9b3caac9 --- /dev/null +++ b/integration_tests/run.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# Run all of the integration test files using `uv run`. +set -eu + +HERE=$(dirname ${BASH_SOURCE:-$0}) +pushd "$HERE" > /dev/null +trap 'popd' ERR + +for file in test_*.py ; do + echo "-----------------" + echo "Running $file..." + uv run $file + echo "Running $file...done." + echo "-----------------" +done + +popd diff --git a/tools/test_uv_loop.py b/integration_tests/test_uv_loop.py similarity index 78% rename from tools/test_uv_loop.py rename to integration_tests/test_uv_loop.py index c3de93ee7a..2327daf11c 100644 --- a/tools/test_uv_loop.py +++ b/integration_tests/test_uv_loop.py @@ -2,7 +2,7 @@ # dependencies = [ # "uvloop>=0.18" # ] -# requires-python = ">=3.11" +# requires-python = ">=3.10" # /// from __future__ import annotations @@ -20,7 +20,8 @@ async def main(): client = AsyncMongoClient() - print(await client.admin.command("ping")) + result = await client.admin.command("ping") + assert result["ok"] uvloop.run(main()) diff --git a/justfile b/justfile index c129b2c199..29ca01fa9b 100644 --- a/justfile +++ b/justfile @@ -73,6 +73,10 @@ setup-tests *args="": teardown-tests: bash .evergreen/scripts/teardown-tests.sh +[group('test')] +integration-tests: + UV_FROZEN="0" bash integration_tests/run.sh + [group('server')] run-server *args="": bash .evergreen/scripts/run-server.sh {{args}} From 16ee09576019e0e3c5032b372ecd821a5e66fe44 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 17 Sep 2025 07:55:52 -0500 Subject: [PATCH 03/10] fix typo --- .github/workflows/test-python.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-python.yml b/.github/workflows/test-python.yml index f6866af873..c1f3c8434a 100644 --- a/.github/workflows/test-python.yml +++ b/.github/workflows/test-python.yml @@ -165,7 +165,7 @@ jobs: run: | just typing - integration_tets: + integration_tests: runs-on: ubuntu-latest name: Integration Tests steps: From 01289b064078c9c06edcc931de2c4a281e42ce72 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 17 Sep 2025 08:12:15 -0500 Subject: [PATCH 04/10] remove stale test --- .github/workflows/test-python.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/test-python.yml b/.github/workflows/test-python.yml index c1f3c8434a..034da752dd 100644 --- a/.github/workflows/test-python.yml +++ b/.github/workflows/test-python.yml @@ -75,8 +75,6 @@ jobs: version: "${{ matrix.mongodb-version }}" - name: Run tests run: uv run --extra test pytest -v - - name: Run uvloop test - run: uv run tools/test_uv_loop.py doctest: runs-on: ubuntu-latest From 8e108fb3bace41f04c316e94e5f3722582c817b8 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 17 Sep 2025 08:13:38 -0500 Subject: [PATCH 05/10] limit perms --- .github/workflows/test-python.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/test-python.yml b/.github/workflows/test-python.yml index 034da752dd..1cee9d45b7 100644 --- a/.github/workflows/test-python.yml +++ b/.github/workflows/test-python.yml @@ -14,6 +14,9 @@ defaults: run: shell: bash -eux {0} +permissions: + contents: read + jobs: static: From 38a4fb6cd5c1b3a1b717ed751ab53564b9eec749 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Thu, 18 Sep 2025 06:48:43 -0500 Subject: [PATCH 06/10] cleanup --- integration_tests/run.sh | 8 +------- justfile | 4 +--- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/integration_tests/run.sh b/integration_tests/run.sh index eb9b3caac9..051e2b8a75 100755 --- a/integration_tests/run.sh +++ b/integration_tests/run.sh @@ -2,16 +2,10 @@ # Run all of the integration test files using `uv run`. set -eu -HERE=$(dirname ${BASH_SOURCE:-$0}) -pushd "$HERE" > /dev/null -trap 'popd' ERR - -for file in test_*.py ; do +for file in integration_tests/test_*.py ; do echo "-----------------" echo "Running $file..." uv run $file echo "Running $file...done." echo "-----------------" done - -popd diff --git a/justfile b/justfile index 29ca01fa9b..30cbd2f35b 100644 --- a/justfile +++ b/justfile @@ -1,7 +1,5 @@ # See https://just.systems/man/en/ for instructions set shell := ["bash", "-c"] -# Do not modify the lock file when running justfile commands. -export UV_FROZEN := "1" # Commonly used command segments. typing_run := "uv run --group typing --extra aws --extra encryption --extra ocsp --extra snappy --extra test --extra zstd" @@ -75,7 +73,7 @@ teardown-tests: [group('test')] integration-tests: - UV_FROZEN="0" bash integration_tests/run.sh + bash integration_tests/run.sh [group('server')] run-server *args="": From d6c6a15c0b8ac7c3471d9bb03844968a89d84b6a Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Thu, 18 Sep 2025 17:11:58 -0500 Subject: [PATCH 07/10] Support running ssl-enabled integration tests --- .github/workflows/test-python.yml | 14 +++++++++----- CONTRIBUTING.md | 2 ++ integration_tests/README.md | 27 +++++++++++++++++++++++++-- integration_tests/test_uv_loop.py | 8 ++++---- test/__init__.py | 7 +++++++ test/asynchronous/__init__.py | 7 +++++++ 6 files changed, 54 insertions(+), 11 deletions(-) diff --git a/.github/workflows/test-python.yml b/.github/workflows/test-python.yml index 1cee9d45b7..a7a8a56837 100644 --- a/.github/workflows/test-python.yml +++ b/.github/workflows/test-python.yml @@ -180,15 +180,19 @@ jobs: python-version: "3.9" - name: Install just run: uv tool install rust-just - - id: setup-mongodb - uses: mongodb-labs/drivers-evergreen-tools@master - with: - version: "8.0" - name: Install dependencies - run: just install + run: | + just install + - name: Start server + run: just run-server - name: Run tests run: | just integration-tests + - name: Start server with SSL + run: just run-server --ssl + - name: Run tests + run: | + SSL=ssl just integration-tests make_sdist: runs-on: ubuntu-latest diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5a628263c7..fb500ca3f8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -419,6 +419,8 @@ The `integration_tests` directory has a set of scripts that verify the usage of To run the tests, use `just integration_tests`. +The tests should be able to run with and without SSL enabled. + ## Specification Tests The MongoDB [specifications repository](https://github.com/mongodb/specifications) diff --git a/integration_tests/README.md b/integration_tests/README.md index d6da378f1a..fb64a9066f 100644 --- a/integration_tests/README.md +++ b/integration_tests/README.md @@ -6,14 +6,37 @@ Each test uses [PEP 723 inline metadata](https://packaging.python.org/en/latest/ The `run.sh` convenience script can be used to run all of the files using `uv`. -When creating a new script, use the following snippet to ensure that the local version of PyMongo is used: +Here is an example header for the script with the inline dependencies: + +```python +# /// script +# dependencies = [ +# "uvloop>=0.18" +# ] +# requires-python = ">=3.10" +# /// +``` + +Here is an example of using the test helper function to create a configured client for the test: ```python -# Use pymongo from parent directory. +import asyncio import sys from pathlib import Path +# Use pymongo from parent directory. root = Path(__file__).parent.parent sys.path.insert(0, str(root)) + +from test.asynchronous import async_simple_test_client # noqa: E402 + + +async def main(): + async with async_simple_test_client() as client: + result = await client.admin.command("ping") + assert result["ok"] + + +asyncio.run(main()) ``` diff --git a/integration_tests/test_uv_loop.py b/integration_tests/test_uv_loop.py index 2327daf11c..88a3ad73ab 100644 --- a/integration_tests/test_uv_loop.py +++ b/integration_tests/test_uv_loop.py @@ -15,13 +15,13 @@ root = Path(__file__).parent.parent sys.path.insert(0, str(root)) -from pymongo import AsyncMongoClient # noqa: E402 +from test.asynchronous import async_simple_test_client # noqa: E402 async def main(): - client = AsyncMongoClient() - result = await client.admin.command("ping") - assert result["ok"] + async with async_simple_test_client() as client: + result = await client.admin.command("ping") + assert result["ok"] uvloop.run(main()) diff --git a/test/__init__.py b/test/__init__.py index d583a72f0f..3821e472d4 100644 --- a/test/__init__.py +++ b/test/__init__.py @@ -1248,6 +1248,13 @@ def teardown(): print_running_clients() +@contextmanager +def async_simple_test_client(): + client_context.init() + yield client_context.client + client_context.client.close() + + def test_cases(suite): """Iterator over all TestCases within a TestSuite.""" for suite_or_case in suite._tests: diff --git a/test/asynchronous/__init__.py b/test/asynchronous/__init__.py index 8ab7ff7219..559a8de7db 100644 --- a/test/asynchronous/__init__.py +++ b/test/asynchronous/__init__.py @@ -1264,6 +1264,13 @@ async def async_teardown(): print_running_clients() +@asynccontextmanager +async def async_simple_test_client(): + await async_client_context.init() + yield async_client_context.client + await async_client_context.client.close() + + def test_cases(suite): """Iterator over all TestCases within a TestSuite.""" for suite_or_case in suite._tests: From bc0c118af1c91690c5f00ab9601ade8d68ce92c6 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Thu, 18 Sep 2025 17:13:07 -0500 Subject: [PATCH 08/10] no need to specify ssl --- .github/workflows/test-python.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-python.yml b/.github/workflows/test-python.yml index a7a8a56837..82b7634ed1 100644 --- a/.github/workflows/test-python.yml +++ b/.github/workflows/test-python.yml @@ -192,7 +192,7 @@ jobs: run: just run-server --ssl - name: Run tests run: | - SSL=ssl just integration-tests + just integration-tests make_sdist: runs-on: ubuntu-latest From e3b6ec60fe105947f37db53f9e5422220ad0b933 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Thu, 18 Sep 2025 17:20:24 -0500 Subject: [PATCH 09/10] wip --- .github/workflows/test-python.yml | 10 ++++++---- test/__init__.py | 2 +- tools/synchro.py | 1 + 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/test-python.yml b/.github/workflows/test-python.yml index 82b7634ed1..bfc74a95f7 100644 --- a/.github/workflows/test-python.yml +++ b/.github/workflows/test-python.yml @@ -183,13 +183,15 @@ jobs: - name: Install dependencies run: | just install - - name: Start server - run: just run-server + - id: setup-mongodb + uses: mongodb-labs/drivers-evergreen-tools@master - name: Run tests run: | just integration-tests - - name: Start server with SSL - run: just run-server --ssl + - id: setup-mongodb-ssl + uses: mongodb-labs/drivers-evergreen-tools@master + with: + ssl: true - name: Run tests run: | just integration-tests diff --git a/test/__init__.py b/test/__init__.py index 3821e472d4..daa48760b7 100644 --- a/test/__init__.py +++ b/test/__init__.py @@ -1249,7 +1249,7 @@ def teardown(): @contextmanager -def async_simple_test_client(): +def simple_test_client(): client_context.init() yield client_context.client client_context.client.close() diff --git a/tools/synchro.py b/tools/synchro.py index e502f96281..22b8727966 100644 --- a/tools/synchro.py +++ b/tools/synchro.py @@ -131,6 +131,7 @@ "async_create_barrier": "create_barrier", "async_barrier_wait": "barrier_wait", "async_joinall": "joinall", + "async_simple_test_client": "simple_test_client", "_async_create_connection": "_create_connection", "pymongo.asynchronous.srv_resolver._SrvResolver.get_hosts": "pymongo.synchronous.srv_resolver._SrvResolver.get_hosts", "dns.asyncresolver.resolve": "dns.resolver.resolve", From 46ea22c02ec7c1c5848148174cbc4807b093b46f Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Tue, 30 Sep 2025 11:41:05 -0500 Subject: [PATCH 10/10] bump to 3.10 --- .github/workflows/test-python.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-python.yml b/.github/workflows/test-python.yml index bff72de66b..0ed23b9d83 100644 --- a/.github/workflows/test-python.yml +++ b/.github/workflows/test-python.yml @@ -177,7 +177,7 @@ jobs: uses: astral-sh/setup-uv@557e51de59eb14aaaba2ed9621916900a91d50c6 # v5 with: enable-cache: true - python-version: "3.9" + python-version: "3.10" - name: Install just run: uv tool install rust-just - name: Install dependencies