@@ -34,6 +34,16 @@ def pytest_addoption(parser):
3434 '--test-pipeline-options' ,
3535 help = 'Options to use in test pipelines. NOTE: Tests may '
3636 'ignore some or all of these options.' )
37+ parser .addoption (
38+ '--enable-test-cleanup' ,
39+ action = 'store_true' ,
40+ default = None ,
41+ help = 'Enable expensive cleanup operations. Auto-enabled in CI.' )
42+ parser .addoption (
43+ '--disable-test-cleanup' ,
44+ action = 'store_true' ,
45+ default = False ,
46+ help = 'Disable expensive cleanup operations even in CI.' )
3747
3848
3949# See pytest.ini for main collection rules.
@@ -101,56 +111,84 @@ def configure_beam_rpc_timeouts():
101111 print ("Successfully configured Beam RPC timeouts" )
102112
103113
114+ def _should_enable_test_cleanup (config ):
115+ """Returns True if expensive cleanup operations should run."""
116+ if config .getoption ('--disable-test-cleanup' ):
117+ result = False
118+ reason = "disabled via --disable-test-cleanup"
119+ elif config .getoption ('--enable-test-cleanup' ):
120+ result = True
121+ reason = "enabled via --enable-test-cleanup"
122+ else :
123+ if os .getenv ('GITHUB_ACTIONS' ) == 'true' :
124+ result = True
125+ reason = "CI detected (GITHUB_ACTIONS)"
126+ elif os .getenv ('CI' ) == 'true' :
127+ result = True
128+ reason = "CI detected (CI)"
129+ elif os .getenv ('CONTINUOUS_INTEGRATION' ) == 'true' :
130+ result = True
131+ reason = "CI detected (CONTINUOUS_INTEGRATION)"
132+ else :
133+ result = False
134+ reason = "local development"
135+
136+ # Log once per session
137+ if not hasattr (config , '_cleanup_decision_logged' ):
138+ print (f"\n [Test Cleanup] Enabled: { result } ({ reason } )" )
139+ config ._cleanup_decision_logged = True
140+
141+ return result
142+
143+
104144@pytest .fixture (autouse = True )
105- def ensure_clean_state ():
145+ def ensure_clean_state (request ):
106146 """
107- Ensure clean state before each test
108- to prevent cross-test contamination.
147+ Ensures clean state between tests to prevent contamination.
148+
149+ Expensive operations (sleeps, extra GC) only run in CI or when
150+ explicitly enabled to keep local tests fast.
109151 """
110152 import gc
111153 import threading
112154 import time
113155
114- # Force garbage collection to clean up any lingering resources
156+ enable_cleanup = _should_enable_test_cleanup (request .config )
157+
115158 gc .collect ()
116159
117- # Log active thread count for debugging
118160 thread_count = threading .active_count ()
119- if thread_count > 50 : # Increased threshold since we see 104 threads
161+ if thread_count > 50 :
120162 print (f"Warning: { thread_count } active threads detected before test" )
121-
122- # Force a brief pause to let threads settle
123- time .sleep (0.5 )
163+ if enable_cleanup :
164+ time .sleep (0.5 )
124165 gc .collect ()
125166
126167 yield
127168
128- # Enhanced cleanup after test
129169 try :
130- # Force more aggressive cleanup
131170 gc .collect ()
132-
133- # Brief pause to let any async operations complete
134- time .sleep (0.1 )
135-
136- # Additional garbage collection
171+ if enable_cleanup :
172+ time .sleep (0.1 )
137173 gc .collect ()
138174 except Exception as e :
139175 print (f"Warning: Cleanup error: { e } " )
140176
141177
142178@pytest .fixture (autouse = True )
143- def enhance_mock_stability ():
144- """Enhance mock stability in DinD environment."""
179+ def enhance_mock_stability (request ):
180+ """Improves mock stability in DinD environment."""
145181 import time
146182
147- # Brief pause before test to ensure clean mock state
148- time .sleep (0.05 )
183+ enable_cleanup = _should_enable_test_cleanup (request .config )
184+
185+ if enable_cleanup :
186+ time .sleep (0.05 )
149187
150188 yield
151189
152- # Brief pause after test to let mocks clean up
153- time .sleep (0.05 )
190+ if enable_cleanup :
191+ time .sleep (0.05 )
154192
155193
156194def pytest_configure (config ):
0 commit comments