This is an automated email from the ASF dual-hosted git repository.

zhengruifeng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/spark.git


The following commit(s) were added to refs/heads/master by this push:
     new 9f772e8453d1 [MINOR][CONNECT][PYTHON][TEST] Fix mock session leakage 
in test_clinet.py
9f772e8453d1 is described below

commit 9f772e8453d10c3a6f0f48d5f869e7c20b9e5371
Author: Yi Hu <[email protected]>
AuthorDate: Thu Jul 16 13:56:01 2026 +0800

    [MINOR][CONNECT][PYTHON][TEST] Fix mock session leakage in test_clinet.py
    
    ### What changes were proposed in this pull request?
    
    Close mock sessions at the end of test_session_hook and its variant
    
    ### Why are the changes needed?
    
    `test_client.py` creates mock `SparkSession` instances that are not 
stopped, leaving `SparkSession._default_session` set globally. On shared test 
workers (e.g., under `pytest-xdist`), subsequent tests calling 
`SparkSession.builder.getOrCreate()` reuse this leftover mock session, causing 
downstream test failures such as `KeyError: 'spark.sql.session.timeZone'`.
    
    ### Does this PR introduce any user-facing change?
    
    No. Test-only change.
    
    ### How was this patch tested?
    
    Verified by running `test_client.py` followed by parity tests on a single 
worker process:
    ```bash
    python -m pytest -v -n 1 --dist loadscope 
python/pyspark/sql/tests/connect/client/test_client.py 
python/pyspark/pandas/tests/connect/diff_frames_ops/test_parity_basic.py
    ```
    against a sparkconnect server
    
    ### Was this patch authored or co-authored using generative AI tooling?
    
    Generated-by:  Gemini
    
    Closes #57282 from Abacn/fix-client-leak.
    
    Authored-by: Yi Hu <[email protected]>
    Signed-off-by: Ruifeng Zheng <[email protected]>
---
 .../sql/tests/connect/client/test_client.py        | 29 +++++++++++++---------
 1 file changed, 17 insertions(+), 12 deletions(-)

diff --git a/python/pyspark/sql/tests/connect/client/test_client.py 
b/python/pyspark/sql/tests/connect/client/test_client.py
index fefbad8960d0..b5bf76d86df4 100644
--- a/python/pyspark/sql/tests/connect/client/test_client.py
+++ b/python/pyspark/sql/tests/connect/client/test_client.py
@@ -425,20 +425,24 @@ class SparkConnectClientTestCase(unittest.TestCase):
         session = (
             
RemoteSparkSession.builder.remote("sc://foo")._registerHook(TestHook).getOrCreate()
         )
-        self.assertEqual(inits, 1)
-        self.assertEqual(calls, 0)
-        session.client._stub = MockService(session.client._session_id)
-        session.client.disable_reattachable_execute()
+        try:
+            self.assertEqual(inits, 1)
+            self.assertEqual(calls, 0)
+            session.client._stub = MockService(session.client._session_id)
+            session.client.disable_reattachable_execute()
 
-        # Called from _execute_and_fetch_as_iterator
-        session.range(1).collect()
-        self.assertEqual(inits, 1)
-        self.assertEqual(calls, 1)
+            # Called from _execute_and_fetch_as_iterator
+            session.range(1).collect()
+            self.assertEqual(inits, 1)
+            self.assertEqual(calls, 1)
 
-        # Called from _execute
-        session.udf.register("test_func", lambda x: x + 1)
-        self.assertEqual(inits, 1)
-        self.assertEqual(calls, 2)
+            # Called from _execute
+            session.udf.register("test_func", lambda x: x + 1)
+            self.assertEqual(inits, 1)
+            self.assertEqual(calls, 2)
+        finally:
+            # Close the session to avoid leaking dummy session inter-test
+            session.stop()
 
     def test_session_hook_preserved_after_new_session(self):
         calls = 0
@@ -473,6 +477,7 @@ class SparkConnectClientTestCase(unittest.TestCase):
             # against the unreachable endpoint at interpreter shutdown.
             new_session.client.close()
             session.client.close()
+            session.stop()
 
     def test_new_session_preserves_custom_channel_builder(self):
         class CustomChannelBuilder(DefaultChannelBuilder):


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to