Skip to content

Commit 993171c

Browse files
authored
PYTHON-4565 - Use pytest markers for test suite configuration (#1741)
1 parent 2725385 commit 993171c

38 files changed

+683
-383
lines changed

.evergreen/run-tests.sh

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ set -o xtrace
3030

3131
AUTH=${AUTH:-noauth}
3232
SSL=${SSL:-nossl}
33-
TEST_SUITES="test/ test/asynchronous/"
33+
TEST_SUITES=""
3434
TEST_ARGS="${*:1}"
3535

3636
export PIP_QUIET=1 # Quiet by default
@@ -96,7 +96,7 @@ if [ -n "$TEST_LOADBALANCER" ]; then
9696
export LOAD_BALANCER=1
9797
export SINGLE_MONGOS_LB_URI="${SINGLE_MONGOS_LB_URI:-mongodb://127.0.0.1:8000/?loadBalanced=true}"
9898
export MULTI_MONGOS_LB_URI="${MULTI_MONGOS_LB_URI:-mongodb://127.0.0.1:8001/?loadBalanced=true}"
99-
export TEST_SUITES="test/test_load_balancer.py"
99+
export TEST_SUITES="load_balancer"
100100
fi
101101

102102
if [ "$SSL" != "nossl" ]; then
@@ -172,7 +172,7 @@ if [ -n "$TEST_ENCRYPTION" ]; then
172172
export PATH=$CRYPT_SHARED_DIR:$PATH
173173
fi
174174
# Only run the encryption tests.
175-
TEST_SUITES="test/test_encryption.py"
175+
TEST_SUITES="encryption"
176176
fi
177177

178178
if [ -n "$TEST_FLE_AZURE_AUTO" ] || [ -n "$TEST_FLE_GCP_AUTO" ]; then
@@ -185,8 +185,7 @@ if [ -n "$TEST_FLE_AZURE_AUTO" ] || [ -n "$TEST_FLE_GCP_AUTO" ]; then
185185
echo "MONGODB_URI unexpectedly contains user credentials in FLE test!";
186186
exit 1
187187
fi
188-
189-
TEST_SUITES="test/test_on_demand_csfle.py"
188+
TEST_SUITES="csfle"
190189
fi
191190

192191
if [ -n "$TEST_INDEX_MANAGEMENT" ]; then
@@ -195,36 +194,36 @@ if [ -n "$TEST_INDEX_MANAGEMENT" ]; then
195194
set +x
196195
export DB_PASSWORD="${DRIVERS_ATLAS_LAMBDA_PASSWORD}"
197196
set -x
198-
TEST_SUITES="test/test_index_management.py"
197+
TEST_SUITES="index_management"
199198
fi
200199

201200
if [ -n "$TEST_DATA_LAKE" ] && [ -z "$TEST_ARGS" ]; then
202-
TEST_SUITES="test/test_data_lake.py"
201+
TEST_SUITES="data_lake"
203202
fi
204203

205204
if [ -n "$TEST_ATLAS" ]; then
206-
TEST_SUITES="test/atlas/test_connection.py"
205+
TEST_SUITES="atlas"
207206
fi
208207

209208
if [ -n "$TEST_OCSP" ]; then
210209
python -m pip install ".[ocsp]"
211-
TEST_SUITES="test/ocsp/test_ocsp.py"
210+
TEST_SUITES="ocsp"
212211
fi
213212

214213
if [ -n "$TEST_AUTH_AWS" ]; then
215214
python -m pip install ".[aws]"
216-
TEST_SUITES="test/auth_aws/test_auth_aws.py"
215+
TEST_SUITES="auth_aws"
217216
fi
218217

219218
if [ -n "$TEST_AUTH_OIDC" ]; then
220219
python -m pip install ".[aws]"
221-
TEST_SUITES="test/auth_oidc/test_auth_oidc.py $TEST_ARGS"
220+
TEST_SUITES="auth_oidc"
222221
fi
223222

224223
if [ -n "$PERF_TEST" ]; then
225224
python -m pip install simplejson
226225
start_time=$(date +%s)
227-
TEST_SUITES="test/performance/perf_test.py"
226+
TEST_SUITES="perf"
228227
fi
229228

230229
echo "Running $AUTH tests over $SSL with python $(which python)"
@@ -254,7 +253,11 @@ PIP_QUIET=0 python -m pip list
254253
if [ -z "$GREEN_FRAMEWORK" ]; then
255254
# Use --capture=tee-sys so pytest prints test output inline:
256255
# https://docs.pytest.org/en/stable/how-to/capture-stdout-stderr.html
257-
python -m pytest -v --capture=tee-sys --durations=5 --maxfail=10 $TEST_SUITES $TEST_ARGS
256+
if [ -z "$TEST_SUITES" ]; then
257+
python -m pytest -v --capture=tee-sys --durations=5 --maxfail=10 $TEST_ARGS
258+
else
259+
python -m pytest -v --capture=tee-sys --durations=5 --maxfail=10 -m $TEST_SUITES $TEST_ARGS
260+
fi
258261
else
259262
python green_framework_test.py $GREEN_FRAMEWORK -v $TEST_ARGS
260263
fi

hatch.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ features = ["test"]
4242
test = "pytest -v --durations=5 --maxfail=10 {args}"
4343
test-eg = "bash ./.evergreen/run-tests.sh {args}"
4444
test-async = "test test/asynchronous/ {args}"
45-
test-mockupdb = ["pip install -U git+https://github.com/ajdavis/mongo-mockup-db@master", "test ./test/mockupdb"]
45+
test-mockupdb = ["pip install -U git+https://github.com/ajdavis/mongo-mockup-db@master", "test -m mockupdb"]
4646

4747
[envs.encryption]
4848
skip-install = true

pyproject.toml

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,9 @@ zstd = ["requirements/zstd.txt"]
7070

7171
[tool.pytest.ini_options]
7272
minversion = "7"
73-
addopts = ["-ra", "--strict-config", "--strict-markers", "--junitxml=xunit-results/TEST-results.xml"]
73+
addopts = ["-ra", "--strict-config", "--strict-markers", "--junitxml=xunit-results/TEST-results.xml", "-m default"]
7474
testpaths = ["test"]
7575
log_cli_level = "INFO"
76-
norecursedirs = ["test/*"]
7776
faulthandler_timeout = 1500
7877
xfail_strict = true
7978
filterwarnings = [
@@ -96,6 +95,20 @@ filterwarnings = [
9695
# https://github.com/dateutil/dateutil/issues/1314
9796
"module:datetime.datetime.utc:DeprecationWarning:dateutil",
9897
]
98+
markers = [
99+
"auth_aws: tests that rely on pymongo-auth-aws",
100+
"auth_oidc: tests that rely on oidc auth",
101+
"ocsp: tests that rely on ocsp",
102+
"atlas: tests that rely on atlas",
103+
"data_lake: tests that rely on atlas data lake",
104+
"perf: benchmark tests",
105+
"index_management: index management tests",
106+
"csfle: client-side field-level encryption tests",
107+
"encryption: encryption tests",
108+
"load_balancer: load balancer tests",
109+
"mockupdb: tests that rely on mockupdb",
110+
"default: default test suite",
111+
]
99112

100113
[tool.mypy]
101114
strict = true

test/asynchronous/conftest.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,9 @@ async def test_setup_and_teardown():
1212
await async_setup()
1313
yield
1414
await async_teardown()
15+
16+
17+
def pytest_collection_modifyitems(items, config):
18+
for item in items:
19+
if not any(item.iter_markers()):
20+
item.add_marker("default")

test/atlas/test_connection.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,16 @@
2020
import unittest
2121
from collections import defaultdict
2222

23+
import pytest
24+
2325
sys.path[0:0] = [""]
2426

2527
import pymongo
2628
from pymongo.ssl_support import HAS_SNI
2729

30+
pytestmark = pytest.mark.atlas
31+
32+
2833
URIS = {
2934
"ATLAS_REPL": os.environ.get("ATLAS_REPL"),
3035
"ATLAS_SHRD": os.environ.get("ATLAS_SHRD"),

test/auth_aws/test_auth_aws.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,21 @@
2020
import unittest
2121
from unittest.mock import patch
2222

23+
import pytest
24+
2325
sys.path[0:0] = [""]
2426

25-
from pymongo_auth_aws import AwsCredential, auth
27+
try:
28+
from pymongo_auth_aws import AwsCredential, auth
29+
except ImportError:
30+
pass
2631

2732
from pymongo import MongoClient
2833
from pymongo.errors import OperationFailure
2934
from pymongo.uri_parser import parse_uri
3035

36+
pytestmark = pytest.mark.auth_aws
37+
3138

3239
class TestAuthAWS(unittest.TestCase):
3340
uri: str

test/auth_oidc/test_auth_oidc.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
from pathlib import Path
2626
from typing import Dict
2727

28+
import pytest
29+
2830
sys.path[0:0] = [""]
2931

3032
from test.unified_format import generate_test_classes
@@ -55,6 +57,8 @@
5557
# Generate unified tests.
5658
globals().update(generate_test_classes(str(TEST_PATH), module=__name__))
5759

60+
pytestmark = pytest.mark.auth_oidc
61+
5862

5963
class OIDCTestBase(unittest.TestCase):
6064
@classmethod
@@ -96,6 +100,7 @@ def fail_point(self, command_args):
96100
client.admin.command("configureFailPoint", cmd_on["configureFailPoint"], mode="off")
97101

98102

103+
@pytest.mark.auth_oidc
99104
class TestAuthOIDCHuman(OIDCTestBase):
100105
uri: str
101106

test/conftest.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,9 @@ def test_setup_and_teardown():
1212
setup()
1313
yield
1414
teardown()
15+
16+
17+
def pytest_collection_modifyitems(items, config):
18+
for item in items:
19+
if not any(item.iter_markers()):
20+
item.add_marker("default")

test/mockupdb/operations.py

Lines changed: 69 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,12 @@
1515

1616
from collections import namedtuple
1717

18-
from mockupdb import OpMsgReply, OpReply
18+
try:
19+
from mockupdb import OpMsgReply, OpReply
20+
21+
_HAVE_MOCKUPDB = True
22+
except ImportError:
23+
_HAVE_MOCKUPDB = False
1924

2025
from pymongo import ReadPreference
2126

@@ -51,67 +56,69 @@
5156
sharded cluster (PYTHON-868).
5257
"""
5358

54-
not_master_reply = OpMsgReply(ok=0, errmsg="not master")
55-
56-
operations = [
57-
Operation(
58-
"find_one",
59-
lambda client: client.db.collection.find_one(),
60-
reply={"cursor": {"id": 0, "firstBatch": []}},
61-
op_type="may-use-secondary",
62-
not_master=not_master_reply,
63-
),
64-
Operation(
65-
"count_documents",
66-
lambda client: client.db.collection.count_documents({}),
67-
reply={"n": 1},
68-
op_type="may-use-secondary",
69-
not_master=not_master_reply,
70-
),
71-
Operation(
72-
"estimated_document_count",
73-
lambda client: client.db.collection.estimated_document_count(),
74-
reply={"n": 1},
75-
op_type="may-use-secondary",
76-
not_master=not_master_reply,
77-
),
78-
Operation(
79-
"aggregate",
80-
lambda client: client.db.collection.aggregate([]),
81-
reply={"cursor": {"id": 0, "firstBatch": []}},
82-
op_type="may-use-secondary",
83-
not_master=not_master_reply,
84-
),
85-
Operation(
86-
"options",
87-
lambda client: client.db.collection.options(),
88-
reply={"cursor": {"id": 0, "firstBatch": []}},
89-
op_type="must-use-primary",
90-
not_master=not_master_reply,
91-
),
92-
Operation(
93-
"command",
94-
lambda client: client.db.command("foo"),
95-
reply={"ok": 1},
96-
op_type="must-use-primary", # Ignores client's read preference.
97-
not_master=not_master_reply,
98-
),
99-
Operation(
100-
"secondary command",
101-
lambda client: client.db.command("foo", read_preference=ReadPreference.SECONDARY),
102-
reply={"ok": 1},
103-
op_type="always-use-secondary",
104-
not_master=OpReply(ok=0, errmsg="node is recovering"),
105-
),
106-
Operation(
107-
"listIndexes",
108-
lambda client: client.db.collection.index_information(),
109-
reply={"cursor": {"id": 0, "firstBatch": []}},
110-
op_type="must-use-primary",
111-
not_master=not_master_reply,
112-
),
113-
]
114-
59+
if _HAVE_MOCKUPDB:
60+
not_master_reply = OpMsgReply(ok=0, errmsg="not master")
61+
62+
operations = [
63+
Operation(
64+
"find_one",
65+
lambda client: client.db.collection.find_one(),
66+
reply={"cursor": {"id": 0, "firstBatch": []}},
67+
op_type="may-use-secondary",
68+
not_master=not_master_reply,
69+
),
70+
Operation(
71+
"count_documents",
72+
lambda client: client.db.collection.count_documents({}),
73+
reply={"n": 1},
74+
op_type="may-use-secondary",
75+
not_master=not_master_reply,
76+
),
77+
Operation(
78+
"estimated_document_count",
79+
lambda client: client.db.collection.estimated_document_count(),
80+
reply={"n": 1},
81+
op_type="may-use-secondary",
82+
not_master=not_master_reply,
83+
),
84+
Operation(
85+
"aggregate",
86+
lambda client: client.db.collection.aggregate([]),
87+
reply={"cursor": {"id": 0, "firstBatch": []}},
88+
op_type="may-use-secondary",
89+
not_master=not_master_reply,
90+
),
91+
Operation(
92+
"options",
93+
lambda client: client.db.collection.options(),
94+
reply={"cursor": {"id": 0, "firstBatch": []}},
95+
op_type="must-use-primary",
96+
not_master=not_master_reply,
97+
),
98+
Operation(
99+
"command",
100+
lambda client: client.db.command("foo"),
101+
reply={"ok": 1},
102+
op_type="must-use-primary", # Ignores client's read preference.
103+
not_master=not_master_reply,
104+
),
105+
Operation(
106+
"secondary command",
107+
lambda client: client.db.command("foo", read_preference=ReadPreference.SECONDARY),
108+
reply={"ok": 1},
109+
op_type="always-use-secondary",
110+
not_master=OpReply(ok=0, errmsg="node is recovering"),
111+
),
112+
Operation(
113+
"listIndexes",
114+
lambda client: client.db.collection.index_information(),
115+
reply={"cursor": {"id": 0, "firstBatch": []}},
116+
op_type="must-use-primary",
117+
not_master=not_master_reply,
118+
),
119+
]
120+
else:
121+
operations = []
115122

116123
_ops_by_name = {op.name: op for op in operations}
117124

test/mockupdb/test_auth_recovering_member.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,20 @@
1515

1616
import unittest
1717

18-
from mockupdb import MockupDB
18+
import pytest
19+
20+
try:
21+
from mockupdb import MockupDB
22+
23+
_HAVE_MOCKUPDB = True
24+
except ImportError:
25+
_HAVE_MOCKUPDB = False
1926

2027
from pymongo import MongoClient
2128
from pymongo.errors import ServerSelectionTimeoutError
2229

30+
pytestmark = pytest.mark.mockupdb
31+
2332

2433
class TestAuthRecoveringMember(unittest.TestCase):
2534
def test_auth_recovering_member(self):

0 commit comments

Comments
 (0)