Skip to content

Commit f27e8e1

Browse files
authored
PYTHON-5149 Convert run-tests.sh to a Python script (#2155)
1 parent 25b2d77 commit f27e8e1

10 files changed

+151
-211
lines changed

.evergreen/config.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ functions:
262262
params:
263263
include_expansions_in_env: [AUTH, SSL, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY,
264264
AWS_SESSION_TOKEN, COVERAGE, PYTHON_BINARY, LIBMONGOCRYPT_URL, MONGODB_URI,
265-
DISABLE_TEST_COMMANDS, GREEN_FRAMEWORK, NO_EXT, COMPRESSORS]
265+
DISABLE_TEST_COMMANDS, GREEN_FRAMEWORK, NO_EXT, COMPRESSORS, MONGODB_API_VERSION]
266266
binary: bash
267267
working_dir: "src"
268268
args: [.evergreen/just.sh, setup-test, "${TEST_NAME}", "${SUB_TEST_NAME}"]

.evergreen/run-tests.sh

+5-65
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
11
#!/bin/bash
2-
set -eux
2+
set -eu
33

44
SCRIPT_DIR=$(dirname ${BASH_SOURCE:-$0})
55
SCRIPT_DIR="$( cd -- "$SCRIPT_DIR" > /dev/null 2>&1 && pwd )"
66
ROOT_DIR="$(dirname $SCRIPT_DIR)"
77

88
pushd $ROOT_DIR
99

10-
export PIP_QUIET=1 # Quiet by default
11-
export PIP_PREFER_BINARY=1 # Prefer binary dists by default
12-
export UV_FROZEN=1 # Do not modify lock files
13-
1410
# Try to source the env file.
1511
if [ -f $SCRIPT_DIR/scripts/env.sh ]; then
1612
echo "Sourcing env inputs"
@@ -25,74 +21,18 @@ if [ -f $SCRIPT_DIR/scripts/test-env.sh ]; then
2521
. $SCRIPT_DIR/scripts/test-env.sh
2622
else
2723
echo "Missing test inputs, please run 'just setup-test'"
24+
exit 1
2825
fi
2926

30-
3127
# Source the local secrets export file if available.
3228
if [ -f "./secrets-export.sh" ]; then
3329
. "./secrets-export.sh"
3430
fi
3531

36-
PYTHON_IMPL=$(uv run python -c "import platform; print(platform.python_implementation())")
37-
38-
# Ensure C extensions if applicable.
39-
if [ -z "${NO_EXT:-}" ] && [ "$PYTHON_IMPL" = "CPython" ]; then
40-
uv run --frozen tools/fail_if_no_c.py
41-
fi
42-
43-
if [ -n "${PYMONGOCRYPT_LIB:-}" ]; then
44-
# Ensure pymongocrypt is working properly.
45-
# shellcheck disable=SC2048
46-
uv run ${UV_ARGS} python -c "import pymongocrypt; print('pymongocrypt version: '+pymongocrypt.__version__)"
47-
# shellcheck disable=SC2048
48-
uv run ${UV_ARGS} python -c "import pymongocrypt; print('libmongocrypt version: '+pymongocrypt.libmongocrypt_version())"
49-
# PATH is updated by configure-env.sh for access to mongocryptd.
50-
fi
51-
52-
PYTHON_IMPL=$(uv run python -c "import platform; print(platform.python_implementation())")
53-
echo "Running ${AUTH:-noauth} tests over ${SSL:-nossl} with python $(uv python find)"
54-
uv run python -c 'import sys; print(sys.version)'
55-
56-
# Show the installed packages
57-
# shellcheck disable=SC2048
32+
# List the packages.
5833
PIP_QUIET=0 uv run ${UV_ARGS} --with pip pip list
5934

60-
# Record the start time for a perf test.
61-
if [ -n "${TEST_PERF:-}" ]; then
62-
start_time=$(date +%s)
63-
fi
64-
65-
# Run the tests, and store the results in Evergreen compatible XUnit XML
66-
# files in the xunit-results/ directory.
67-
TEST_ARGS=${TEST_ARGS}
68-
if [ "$#" -ne 0 ]; then
69-
TEST_ARGS="$*"
70-
fi
71-
echo "Running tests with $TEST_ARGS and uv args $UV_ARGS..."
72-
if [ -z "${GREEN_FRAMEWORK:-}" ]; then
73-
# shellcheck disable=SC2048
74-
uv run ${UV_ARGS} pytest $TEST_ARGS
75-
else
76-
# shellcheck disable=SC2048
77-
uv run ${UV_ARGS} green_framework_test.py $GREEN_FRAMEWORK -v $TEST_ARGS
78-
fi
79-
echo "Running tests with $TEST_ARGS... done."
80-
81-
# Handle perf test post actions.
82-
if [ -n "${TEST_PERF:-}" ]; then
83-
end_time=$(date +%s)
84-
elapsed_secs=$((end_time-start_time))
85-
86-
cat results.json
87-
88-
echo "{\"failures\": 0, \"results\": [{\"status\": \"pass\", \"exit_code\": 0, \"test_file\": \"BenchMarkTests\", \"start\": $start_time, \"end\": $end_time, \"elapsed\": $elapsed_secs}]}" > report.json
89-
90-
cat report.json
91-
fi
92-
93-
# Handle coverage post actions.
94-
if [ -n "${COVERAGE:-}" ]; then
95-
rm -rf .pytest_cache
96-
fi
35+
# Start the test runner.
36+
uv run ${UV_ARGS} .evergreen/scripts/run_tests.py
9737

9838
popd

.evergreen/scripts/run_tests.py

+119
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
from __future__ import annotations
2+
3+
import json
4+
import logging
5+
import os
6+
import platform
7+
import shutil
8+
import sys
9+
from datetime import datetime
10+
from pathlib import Path
11+
12+
import pytest
13+
14+
HERE = Path(__file__).absolute().parent
15+
ROOT = HERE.parent.parent
16+
AUTH = os.environ.get("AUTH", "noauth")
17+
SSL = os.environ.get("SSL", "nossl")
18+
UV_ARGS = os.environ.get("UV_ARGS", "")
19+
TEST_PERF = os.environ.get("TEST_PERF")
20+
GREEN_FRAMEWORK = os.environ.get("GREEN_FRAMEWORK")
21+
TEST_ARGS = os.environ.get("TEST_ARGS", "").split()
22+
23+
LOGGER = logging.getLogger(__name__)
24+
logging.basicConfig(level=logging.INFO, format="%(levelname)-8s %(message)s")
25+
26+
27+
def handle_perf(start_time: datetime):
28+
end_time = datetime.now()
29+
elapsed_secs = (end_time - start_time).total_seconds()
30+
with open("results.json") as fid:
31+
results = json.load(fid)
32+
LOGGER.info("results.json:\n%s", json.dumps(results, indent=2))
33+
34+
results = dict(
35+
status="PASS",
36+
exit_code=0,
37+
test_file="BenchMarkTests",
38+
start=int(start_time.timestamp()),
39+
end=int(end_time.timestamp()),
40+
elapsed=elapsed_secs,
41+
)
42+
report = dict(failures=0, results=[results])
43+
LOGGER.info("report.json\n%s", json.dumps(report, indent=2))
44+
45+
with open("report.json", "w", newline="\n") as fid:
46+
json.dump(report, fid)
47+
48+
49+
def handle_green_framework() -> None:
50+
if GREEN_FRAMEWORK == "eventlet":
51+
import eventlet
52+
53+
# https://github.com/eventlet/eventlet/issues/401
54+
eventlet.sleep()
55+
eventlet.monkey_patch()
56+
elif GREEN_FRAMEWORK == "gevent":
57+
from gevent import monkey
58+
59+
monkey.patch_all()
60+
61+
# Never run async tests with a framework.
62+
if len(TEST_ARGS) <= 1:
63+
TEST_ARGS.extend(["-m", "not default_async and default"])
64+
else:
65+
for i in range(len(TEST_ARGS) - 1):
66+
if "-m" in TEST_ARGS[i]:
67+
TEST_ARGS[i + 1] = f"not default_async and {TEST_ARGS[i + 1]}"
68+
69+
LOGGER.info(f"Running tests with {GREEN_FRAMEWORK}...")
70+
71+
72+
def handle_c_ext() -> None:
73+
if platform.python_implementation() != "CPython":
74+
return
75+
sys.path.insert(0, str(ROOT / "tools"))
76+
from fail_if_no_c import main as fail_if_no_c
77+
78+
fail_if_no_c()
79+
80+
81+
def handle_pymongocrypt() -> None:
82+
import pymongocrypt
83+
84+
LOGGER.info(f"pymongocrypt version: {pymongocrypt.__version__})")
85+
LOGGER.info(f"libmongocrypt version: {pymongocrypt.libmongocrypt_version()})")
86+
87+
88+
def run() -> None:
89+
# Handle green framework first so they can patch modules.
90+
if GREEN_FRAMEWORK:
91+
handle_green_framework()
92+
93+
# Ensure C extensions if applicable.
94+
if not os.environ.get("NO_EXT"):
95+
handle_c_ext()
96+
97+
if os.environ.get("PYMONGOCRYPT_LIB"):
98+
handle_pymongocrypt()
99+
100+
LOGGER.info(f"Test setup:\n{AUTH=}\n{SSL=}\n{UV_ARGS=}\n{TEST_ARGS=}")
101+
102+
# Record the start time for a perf test.
103+
if TEST_PERF:
104+
start_time = datetime.now()
105+
106+
# Run the tests.
107+
pytest.main(TEST_ARGS)
108+
109+
# Handle perf test post actions.
110+
if TEST_PERF:
111+
handle_perf(start_time)
112+
113+
# Handle coverage post actions.
114+
if os.environ.get("COVERAGE"):
115+
shutil.rmtree(".pytest_cache", ignore_errors=True)
116+
117+
118+
if __name__ == "__main__":
119+
run()

.evergreen/scripts/setup_tests.py

+3
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,9 @@ def handle_test_env() -> None:
228228

229229
write_env("AUTH", AUTH)
230230
write_env("SSL", SSL)
231+
write_env("PIP_QUIET") # Quiet by default.
232+
write_env("PIP_PREFER_BINARY") # Prefer binary dists by default.
233+
write_env("UV_FROZEN") # Do not modify lock files.
231234

232235
# Skip CSOT tests on non-linux platforms.
233236
if PLATFORM != "linux":

.evergreen/scripts/teardown-tests.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,6 @@ if [ -n "${TEST_ENCRYPTION:-}" ]; then
2424
fi
2525

2626
# Shut down load balancer if applicable.
27-
if [ -n "${TEST_LOADBALANCER:-}" ]; then
27+
if [ -n "${TEST_LOAD_BALANCER:-}" ]; then
2828
bash "${DRIVERS_TOOLS}"/.evergreen/run-load-balancer.sh stop
2929
fi

green_framework_test.py

-117
This file was deleted.

pyproject.toml

-1
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,6 @@ dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?)|dummy.*)$"
234234
"RET", "ARG", "F405", "B028", "PGH001", "B018", "F403", "RUF015", "E731", "B007",
235235
"UP031", "F401", "B023", "F811"]
236236
"tools/*.py" = ["T201"]
237-
"green_framework_test.py" = ["T201"]
238237
"hatch_build.py" = ["S"]
239238
"_setup.py" = ["SIM112"]
240239

test/asynchronous/helpers.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@
8181

8282
COMPRESSORS = os.environ.get("COMPRESSORS")
8383
MONGODB_API_VERSION = os.environ.get("MONGODB_API_VERSION")
84-
TEST_LOADBALANCER = bool(os.environ.get("TEST_LOADBALANCER"))
84+
TEST_LOADBALANCER = bool(os.environ.get("TEST_LOAD_BALANCER"))
8585
TEST_SERVERLESS = bool(os.environ.get("TEST_SERVERLESS"))
8686
SINGLE_MONGOS_LB_URI = os.environ.get("SINGLE_MONGOS_LB_URI")
8787
MULTI_MONGOS_LB_URI = os.environ.get("MULTI_MONGOS_LB_URI")

test/helpers.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@
8181

8282
COMPRESSORS = os.environ.get("COMPRESSORS")
8383
MONGODB_API_VERSION = os.environ.get("MONGODB_API_VERSION")
84-
TEST_LOADBALANCER = bool(os.environ.get("TEST_LOADBALANCER"))
84+
TEST_LOADBALANCER = bool(os.environ.get("TEST_LOAD_BALANCER"))
8585
TEST_SERVERLESS = bool(os.environ.get("TEST_SERVERLESS"))
8686
SINGLE_MONGOS_LB_URI = os.environ.get("SINGLE_MONGOS_LB_URI")
8787
MULTI_MONGOS_LB_URI = os.environ.get("MULTI_MONGOS_LB_URI")

0 commit comments

Comments
 (0)