4444DEFAULT_PYTHON_VERSION = "3.14"
4545
4646UNIT_TEST_PYTHON_VERSIONS : List [str ] = [
47- "3.8" ,
48- "3.9" ,
47+ # "3.8",
48+ # "3.9",
4949 "3.10" ,
5050 "3.11" ,
5151 "3.12" ,
5252 "3.13" ,
5353 "3.14" ,
5454]
5555ALL_PYTHON = list (UNIT_TEST_PYTHON_VERSIONS )
56- ALL_PYTHON .extend (["3.7 " ])
56+ ALL_PYTHON .extend (["3.9 " ])
5757UNIT_TEST_STANDARD_DEPENDENCIES = [
5858 "mock" ,
5959 "asyncmock" ,
@@ -318,7 +318,7 @@ def unit(session, protobuf_implementation, install_extras=True):
318318 )
319319
320320
321- def install_systemtest_dependencies (session , * constraints ):
321+ def install_systemtest_dependencies (session , use_extras = True , * constraints ):
322322 # Use pre-release gRPC for system tests.
323323 # Exclude version 1.52.0rc1 which has a known issue.
324324 # See https://github.com/grpc/grpc/issues/32163
@@ -335,10 +335,13 @@ def install_systemtest_dependencies(session, *constraints):
335335 if SYSTEM_TEST_DEPENDENCIES :
336336 session .install ("-e" , * SYSTEM_TEST_DEPENDENCIES , * constraints )
337337
338- if SYSTEM_TEST_EXTRAS_BY_PYTHON :
339- extras = SYSTEM_TEST_EXTRAS_BY_PYTHON .get (session .python , [])
340- elif SYSTEM_TEST_EXTRAS :
341- extras = SYSTEM_TEST_EXTRAS
338+ if use_extras :
339+ if SYSTEM_TEST_EXTRAS_BY_PYTHON :
340+ extras = SYSTEM_TEST_EXTRAS_BY_PYTHON .get (session .python , [])
341+ elif SYSTEM_TEST_EXTRAS :
342+ extras = SYSTEM_TEST_EXTRAS
343+ else :
344+ extras = []
342345 else :
343346 extras = []
344347
@@ -348,161 +351,123 @@ def install_systemtest_dependencies(session, *constraints):
348351 session .install ("-e" , "." , * constraints )
349352
350353
351- @nox .session (python = SYSTEM_TEST_PYTHON_VERSIONS )
352- @_calculate_duration
353- def system (session ):
354- """Run the system test suite."""
354+ def _run_system_test_logic (session , test_type ):
355+ """Shared logic for system, system_noextras, and compliance tests."""
355356 constraints_path = str (
356357 CURRENT_DIRECTORY / "testing" / f"constraints-{ session .python } .txt"
357358 )
358- system_test_path = os .path .join ("tests" , "system.py" )
359- system_test_folder_path = os .path .join ("tests" , "system" )
359+
360+ if test_type == "compliance" :
361+ test_path = os .path .join ("tests" , "sqlalchemy_dialect_compliance" )
362+ else :
363+ test_path = os .path .join ("tests" , "system" )
364+ if not os .path .exists (test_path ):
365+ test_path = os .path .join ("tests" , "system.py" )
360366
361367 if not os .environ .get ("GOOGLE_APPLICATION_CREDENTIALS" , "" ):
362368 session .skip (
363369 "Credentials must be set via environment variable GOOGLE_APPLICATION_CREDENTIALS"
364370 )
365371
366- # Check the value of `RUN_SYSTEM_TESTS` env var. It defaults to true.
367- if os .environ .get ("RUN_SYSTEM_TESTS" , "true" ) == "false" :
368- session .skip ("RUN_SYSTEM_TESTS is set to false, skipping" )
372+ # Check for specific test type skip logic
373+ if test_type == "compliance" :
374+ if os .environ .get ("RUN_COMPLIANCE_TESTS" , "true" ) == "false" :
375+ session .skip ("RUN_COMPLIANCE_TESTS is set to false, skipping" )
376+ else :
377+ if os .environ .get ("RUN_SYSTEM_TESTS" , "true" ) == "false" :
378+ session .skip ("RUN_SYSTEM_TESTS is set to false, skipping" )
379+
369380 # Install pyopenssl for mTLS testing.
370381 if os .environ .get ("GOOGLE_API_USE_CLIENT_CERTIFICATE" , "false" ) == "true" :
371382 session .install ("pyopenssl" )
372383
373- system_test_exists = os .path .exists (system_test_path )
374- system_test_folder_exists = os .path .exists (system_test_folder_path )
375- # Sanity check: only run tests if found.
376- if not system_test_exists and not system_test_folder_exists :
377- session .skip ("System tests were not found" )
378-
379- install_systemtest_dependencies (session , "-c" , constraints_path )
384+ if not os .path .exists (test_path ):
385+ session .skip (f"Test path { test_path } not found" )
386+
387+ # Installation logic
388+ if test_type == "compliance" :
389+ session .install (
390+ "mock" ,
391+ "pytest" ,
392+ "pytest-rerunfailures" ,
393+ "google-cloud-testutils" ,
394+ "-c" ,
395+ constraints_path ,
396+ )
397+ if session .python in ["3.12" , "3.13" , "3.14" ]:
398+ extras = "[tests,geography,alembic]"
399+ else :
400+ extras = "[tests]"
401+ session .install ("-e" , f".{ extras } " , "-c" , constraints_path )
402+ else :
403+ install_systemtest_dependencies (
404+ session , (test_type == "system" ), "-c" , constraints_path
405+ )
380406
381407 session .run ("python" , "-m" , "pip" , "freeze" )
382408
383- # Run py.test against the system tests.
384- if system_test_exists :
409+ # Execution logic
410+ if test_type == "compliance" :
385411 session .run (
386412 "py.test" ,
387- "--quiet" ,
388- f"--junitxml=system_{ session .python } _sponge_log.xml" ,
389- system_test_path ,
413+ "-vv" ,
414+ f"--junitxml=compliance_{ session .python } _sponge_log.xml" ,
415+ "--reruns=3" ,
416+ "--reruns-delay=60" ,
417+ "--only-rerun=Exceeded rate limits" ,
418+ "--only-rerun=Already Exists" ,
419+ "--only-rerun=Not found" ,
420+ "--only-rerun=Cannot execute DML over a non-existent table" ,
421+ "--only-rerun=Job exceeded rate limits" ,
422+ test_path ,
390423 * session .posargs ,
424+ env = {"SQLALCHEMY_SILENCE_UBER_WARNING" : "1" },
391425 )
392- if system_test_folder_exists :
426+ else :
393427 session .run (
394428 "py.test" ,
395429 "--quiet" ,
396430 f"--junitxml=system_{ session .python } _sponge_log.xml" ,
397- system_test_folder_path ,
431+ test_path ,
398432 * session .posargs ,
399433 )
400434
401435
402436@nox .session (python = SYSTEM_TEST_PYTHON_VERSIONS )
437+ @nox .parametrize ("test_type" , ["system" , "system_noextras" , "compliance" ])
403438@_calculate_duration
404- def system_noextras (session ):
439+ def system (session , test_type ):
405440 """Run the system test suite."""
406- constraints_path = str (
407- CURRENT_DIRECTORY / "testing" / f"constraints-{ session .python } .txt"
408- )
409- system_test_path = os .path .join ("tests" , "system.py" )
410- system_test_folder_path = os .path .join ("tests" , "system" )
411-
412- if not os .environ .get ("GOOGLE_APPLICATION_CREDENTIALS" , "" ):
413- session .skip (
414- "Credentials must be set via environment variable GOOGLE_APPLICATION_CREDENTIALS"
415- )
416-
417- # Check the value of `RUN_SYSTEM_TESTS` env var. It defaults to true.
418- if os .environ .get ("RUN_SYSTEM_TESTS" , "true" ) == "false" :
419- session .skip ("RUN_SYSTEM_TESTS is set to false, skipping" )
420- # Install pyopenssl for mTLS testing.
421- if os .environ .get ("GOOGLE_API_USE_CLIENT_CERTIFICATE" , "false" ) == "true" :
422- session .install ("pyopenssl" )
423-
424- system_test_exists = os .path .exists (system_test_path )
425- system_test_folder_exists = os .path .exists (system_test_folder_path )
426- # Sanity check: only run tests if found.
427- if not system_test_exists and not system_test_folder_exists :
428- session .skip ("System tests were not found" )
441+ if test_type == "compliance" :
442+ if session .python != DEFAULT_PYTHON_VERSION :
443+ session .skip (
444+ f"Compliance tests only run on latest Python: { DEFAULT_PYTHON_VERSION } "
445+ )
446+ elif test_type == "system_noextras" :
447+ if session .python not in (
448+ SYSTEM_TEST_PYTHON_VERSIONS [0 ],
449+ SYSTEM_TEST_PYTHON_VERSIONS [- 1 ],
450+ ):
451+ session .skip (
452+ f"system_noextras only runs on oldest ({ SYSTEM_TEST_PYTHON_VERSIONS [0 ]} ) "
453+ f"and newest ({ SYSTEM_TEST_PYTHON_VERSIONS [- 1 ]} ) supported Python versions"
454+ )
429455
430- global SYSTEM_TEST_EXTRAS_BY_PYTHON
431- SYSTEM_TEST_EXTRAS_BY_PYTHON = False
432- install_systemtest_dependencies (session , "-c" , constraints_path )
456+ _run_system_test_logic (session , test_type )
433457
434- session .run ("python" , "-m" , "pip" , "freeze" )
435458
436- # Run py.test against the system tests.
437- if system_test_exists :
438- session .run (
439- "py.test" ,
440- "--quiet" ,
441- f"--junitxml=system_{ session .python } _sponge_log.xml" ,
442- system_test_path ,
443- * session .posargs ,
444- )
445- if system_test_folder_exists :
446- session .run (
447- "py.test" ,
448- "--quiet" ,
449- f"--junitxml=system_{ session .python } _sponge_log.xml" ,
450- system_test_folder_path ,
451- * session .posargs ,
452- )
459+ @nox .session (python = SYSTEM_TEST_PYTHON_VERSIONS )
460+ @_calculate_duration
461+ def system_noextras (session ):
462+ """Run the system test suite without extras."""
463+ _run_system_test_logic (session , "system_noextras" )
453464
454465
455466@nox .session (python = SYSTEM_TEST_PYTHON_VERSIONS [- 1 ])
456467@_calculate_duration
457468def compliance (session ):
458469 """Run the SQLAlchemy dialect-compliance system tests"""
459- constraints_path = str (
460- CURRENT_DIRECTORY / "testing" / f"constraints-{ session .python } .txt"
461- )
462- system_test_folder_path = os .path .join ("tests" , "sqlalchemy_dialect_compliance" )
463-
464- if os .environ .get ("RUN_COMPLIANCE_TESTS" , "true" ) == "false" :
465- session .skip ("RUN_COMPLIANCE_TESTS is set to false, skipping" )
466- if os .environ .get ("GOOGLE_API_USE_CLIENT_CERTIFICATE" , "false" ) == "true" :
467- session .install ("pyopenssl" )
468- if not os .path .exists (system_test_folder_path ):
469- session .skip ("Compliance tests were not found" )
470-
471- session .install (
472- "mock" ,
473- "pytest" ,
474- "pytest-rerunfailures" ,
475- "google-cloud-testutils" ,
476- "-c" ,
477- constraints_path ,
478- )
479- if session .python in ["3.12" , "3.13" , "3.14" ]:
480- extras = "[tests,geography,alembic]"
481- else :
482- extras = "[tests]"
483- session .install ("-e" , f".{ extras } " , "-c" , constraints_path )
484-
485- session .run ("python" , "-m" , "pip" , "freeze" )
486-
487- session .run (
488- "py.test" ,
489- "-vv" ,
490- f"--junitxml=compliance_{ session .python } _sponge_log.xml" ,
491- "--reruns=3" ,
492- "--reruns-delay=60" ,
493- "--only-rerun=Exceeded rate limits" ,
494- "--only-rerun=Already Exists" ,
495- "--only-rerun=Not found" ,
496- "--only-rerun=Cannot execute DML over a non-existent table" ,
497- "--only-rerun=Job exceeded rate limits" ,
498- system_test_folder_path ,
499- * session .posargs ,
500- # To suppress the "Deprecated API features detected!" warning when
501- # features not compatible with 2.0 are detected, use a value of "1"
502- env = {
503- "SQLALCHEMY_SILENCE_UBER_WARNING" : "1" ,
504- },
505- )
470+ _run_system_test_logic (session , "compliance" )
506471
507472
508473@nox .session (python = DEFAULT_PYTHON_VERSION )
0 commit comments