From 154e618e93f7a2859dd21babd720210f656c24a3 Mon Sep 17 00:00:00 2001 From: Muawiya-contact Date: Mon, 18 May 2026 22:21:59 +0500 Subject: [PATCH 1/7] test(python-client): fix silent-skip anti-pattern in test_gremlin.py setUpClass - Remove automatic connectivity probe that silently skipped all 6 Gremlin integration tests on 404 / timeout / connection error - Endpoint failures now surface as FAILED, not SKIPPED - Add explicit opt-in skip via SKIP_GREMLIN_TESTS env variable - Document Docker-based local setup in inline comments Fixes #327 Related: #325, #320 Signed-off-by: Muawiya-contact --- .../src/tests/api/test_gremlin.py | 50 ++++++++++++------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/hugegraph-python-client/src/tests/api/test_gremlin.py b/hugegraph-python-client/src/tests/api/test_gremlin.py index 227a526c..b9881316 100644 --- a/hugegraph-python-client/src/tests/api/test_gremlin.py +++ b/hugegraph-python-client/src/tests/api/test_gremlin.py @@ -15,6 +15,7 @@ # specific language governing permissions and limitations # under the License. +import os import unittest from unittest import mock @@ -28,9 +29,21 @@ class TestGremlin(unittest.TestCase): client = None gremlin = None skip_gremlin_tests = False - @classmethod def setUpClass(cls): + # To run these tests locally, start HugeGraph via Docker: + # docker run -d -p 8080:8080 hugegraph/hugegraph:latest + # + # To explicitly skip Gremlin tests in CI or locally, set: + # SKIP_GREMLIN_TESTS=true + # + # Do NOT add automatic skip logic based on connectivity probes. + # Endpoint failures must surface as FAILED tests, not SKIPPED. + if os.environ.get("SKIP_GREMLIN_TESTS", "").lower() == "true": + raise unittest.SkipTest( + "Skipping Gremlin tests: SKIP_GREMLIN_TESTS=true" + ) + cls.client = ClientUtils() cls.gremlin = cls.client.gremlin cls.client.clear_graph_all_data() @@ -38,19 +51,6 @@ def setUpClass(cls): cls.client.init_vertex_label() cls.client.init_edge_label() - try: - # Skip only when the gremlin probe itself shows the endpoint is unavailable. - cls.gremlin.exec("1 + 1") - except NotFoundError as e: - error_str = str(e) - if any( - marker in error_str - for marker in ["404", "Not Found", "timed out", "Connection refused", "Gremlin can't get results"] - ): - cls.skip_gremlin_tests = True - else: - raise - @classmethod def tearDownClass(cls): if not cls.skip_gremlin_tests: @@ -125,12 +125,28 @@ def test_set_up_class_reraises_non_probe_failures(self): self.assertFalse(TestGremlin.skip_gremlin_tests) - def test_set_up_class_skips_when_gremlin_probe_returns_not_found(self): + def test_set_up_class_reraises_probe_errors(self): + # When the gremlin client raises NotFoundError during operations, + # do not silently skip — surface the error so tests fail. with mock.patch(f"{TestGremlin.__module__}.ClientUtils") as client_utils_cls: client = client_utils_cls.return_value client.gremlin = mock.Mock() client.gremlin.exec.side_effect = NotFoundError("404 Not Found") - TestGremlin.setUpClass() + with self.assertRaises(NotFoundError): + TestGremlin.setUpClass() - self.assertTrue(TestGremlin.skip_gremlin_tests) + self.assertFalse(TestGremlin.skip_gremlin_tests) + + def test_set_up_class_skips_when_env_var_set(self): + # Explicit opt-in skip via environment variable is supported. + with mock.patch(f"{TestGremlin.__module__}.ClientUtils") as client_utils_cls: + client = client_utils_cls.return_value + client.gremlin = mock.Mock() + # Ensure the env var causes a SkipTest regardless of client behavior. + os.environ["SKIP_GREMLIN_TESTS"] = "true" + try: + with self.assertRaises(unittest.SkipTest): + TestGremlin.setUpClass() + finally: + os.environ.pop("SKIP_GREMLIN_TESTS", None) From 7a77a7443dacdbeca89e855f88031bc45f161583 Mon Sep 17 00:00:00 2001 From: Muawiya Amir Date: Wed, 20 May 2026 08:49:24 +0500 Subject: [PATCH 2/7] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- hugegraph-python-client/src/tests/api/test_gremlin.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/hugegraph-python-client/src/tests/api/test_gremlin.py b/hugegraph-python-client/src/tests/api/test_gremlin.py index b9881316..9f545cbf 100644 --- a/hugegraph-python-client/src/tests/api/test_gremlin.py +++ b/hugegraph-python-client/src/tests/api/test_gremlin.py @@ -144,9 +144,6 @@ def test_set_up_class_skips_when_env_var_set(self): client = client_utils_cls.return_value client.gremlin = mock.Mock() # Ensure the env var causes a SkipTest regardless of client behavior. - os.environ["SKIP_GREMLIN_TESTS"] = "true" - try: + with mock.patch.dict(os.environ, {"SKIP_GREMLIN_TESTS": "true"}): with self.assertRaises(unittest.SkipTest): TestGremlin.setUpClass() - finally: - os.environ.pop("SKIP_GREMLIN_TESTS", None) From ae157f08d666f3b0b3fe6175cc840fa24d0be9ac Mon Sep 17 00:00:00 2001 From: Muawiya-contact Date: Wed, 20 May 2026 08:58:45 +0500 Subject: [PATCH 3/7] test: address Copilot review comments on setUpClass behavior tests --- hugegraph-python-client/print_env.py | 2 ++ hugegraph-python-client/run_setUpClass.py | 9 +++++++++ hugegraph-python-client/src/tests/api/test_gremlin.py | 11 ++++------- 3 files changed, 15 insertions(+), 7 deletions(-) create mode 100644 hugegraph-python-client/print_env.py create mode 100644 hugegraph-python-client/run_setUpClass.py diff --git a/hugegraph-python-client/print_env.py b/hugegraph-python-client/print_env.py new file mode 100644 index 00000000..3676a559 --- /dev/null +++ b/hugegraph-python-client/print_env.py @@ -0,0 +1,2 @@ +import os +print(os.environ.get('SKIP_GREMLIN_TESTS')) diff --git a/hugegraph-python-client/run_setUpClass.py b/hugegraph-python-client/run_setUpClass.py new file mode 100644 index 00000000..707882f8 --- /dev/null +++ b/hugegraph-python-client/run_setUpClass.py @@ -0,0 +1,9 @@ +import os, sys +sys.path.insert(0, 'src') +os.environ['SKIP_GREMLIN_TESTS'] = 'true' +from tests.api.test_gremlin import TestGremlin +try: + TestGremlin.setUpClass() + print('NO_SKIP') +except Exception as e: + print('RAISED', type(e).__name__, str(e)) diff --git a/hugegraph-python-client/src/tests/api/test_gremlin.py b/hugegraph-python-client/src/tests/api/test_gremlin.py index 9f545cbf..61e83c14 100644 --- a/hugegraph-python-client/src/tests/api/test_gremlin.py +++ b/hugegraph-python-client/src/tests/api/test_gremlin.py @@ -125,18 +125,15 @@ def test_set_up_class_reraises_non_probe_failures(self): self.assertFalse(TestGremlin.skip_gremlin_tests) - def test_set_up_class_reraises_probe_errors(self): - # When the gremlin client raises NotFoundError during operations, - # do not silently skip — surface the error so tests fail. + def test_set_up_class_no_longer_probes_gremlin(self): + # After removing the probe, setUpClass should NOT call gremlin.exec at all. with mock.patch(f"{TestGremlin.__module__}.ClientUtils") as client_utils_cls: client = client_utils_cls.return_value client.gremlin = mock.Mock() - client.gremlin.exec.side_effect = NotFoundError("404 Not Found") - with self.assertRaises(NotFoundError): - TestGremlin.setUpClass() + TestGremlin.setUpClass() - self.assertFalse(TestGremlin.skip_gremlin_tests) + client.gremlin.exec.assert_not_called() def test_set_up_class_skips_when_env_var_set(self): # Explicit opt-in skip via environment variable is supported. From a894c90187e2a558b4bb194aa93df5890ce67b6d Mon Sep 17 00:00:00 2001 From: Muawiya-contact Date: Wed, 20 May 2026 08:59:37 +0500 Subject: [PATCH 4/7] chore: remove temporary debug scripts --- hugegraph-python-client/print_env.py | 2 -- hugegraph-python-client/run_setUpClass.py | 9 --------- 2 files changed, 11 deletions(-) delete mode 100644 hugegraph-python-client/print_env.py delete mode 100644 hugegraph-python-client/run_setUpClass.py diff --git a/hugegraph-python-client/print_env.py b/hugegraph-python-client/print_env.py deleted file mode 100644 index 3676a559..00000000 --- a/hugegraph-python-client/print_env.py +++ /dev/null @@ -1,2 +0,0 @@ -import os -print(os.environ.get('SKIP_GREMLIN_TESTS')) diff --git a/hugegraph-python-client/run_setUpClass.py b/hugegraph-python-client/run_setUpClass.py deleted file mode 100644 index 707882f8..00000000 --- a/hugegraph-python-client/run_setUpClass.py +++ /dev/null @@ -1,9 +0,0 @@ -import os, sys -sys.path.insert(0, 'src') -os.environ['SKIP_GREMLIN_TESTS'] = 'true' -from tests.api.test_gremlin import TestGremlin -try: - TestGremlin.setUpClass() - print('NO_SKIP') -except Exception as e: - print('RAISED', type(e).__name__, str(e)) From 965e8fa9521069f87af47c79f63e045a3330c300 Mon Sep 17 00:00:00 2001 From: Muawiya-contact Date: Wed, 20 May 2026 13:33:37 +0500 Subject: [PATCH 5/7] style: apply ruff formatting to test_gremlin.py --- hugegraph-python-client/src/tests/api/test_gremlin.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/hugegraph-python-client/src/tests/api/test_gremlin.py b/hugegraph-python-client/src/tests/api/test_gremlin.py index 61e83c14..cced2f02 100644 --- a/hugegraph-python-client/src/tests/api/test_gremlin.py +++ b/hugegraph-python-client/src/tests/api/test_gremlin.py @@ -29,6 +29,7 @@ class TestGremlin(unittest.TestCase): client = None gremlin = None skip_gremlin_tests = False + @classmethod def setUpClass(cls): # To run these tests locally, start HugeGraph via Docker: @@ -40,9 +41,7 @@ def setUpClass(cls): # Do NOT add automatic skip logic based on connectivity probes. # Endpoint failures must surface as FAILED tests, not SKIPPED. if os.environ.get("SKIP_GREMLIN_TESTS", "").lower() == "true": - raise unittest.SkipTest( - "Skipping Gremlin tests: SKIP_GREMLIN_TESTS=true" - ) + raise unittest.SkipTest("Skipping Gremlin tests: SKIP_GREMLIN_TESTS=true") cls.client = ClientUtils() cls.gremlin = cls.client.gremlin From 6bd18bf394eb0673f4c789b018ff5be10fb5979b Mon Sep 17 00:00:00 2001 From: Muawiya-contact Date: Wed, 20 May 2026 14:21:20 +0500 Subject: [PATCH 6/7] style: combine nested with statements to fix SIM117 --- hugegraph-python-client/src/tests/api/test_gremlin.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/hugegraph-python-client/src/tests/api/test_gremlin.py b/hugegraph-python-client/src/tests/api/test_gremlin.py index cced2f02..d47f7bc6 100644 --- a/hugegraph-python-client/src/tests/api/test_gremlin.py +++ b/hugegraph-python-client/src/tests/api/test_gremlin.py @@ -140,6 +140,5 @@ def test_set_up_class_skips_when_env_var_set(self): client = client_utils_cls.return_value client.gremlin = mock.Mock() # Ensure the env var causes a SkipTest regardless of client behavior. - with mock.patch.dict(os.environ, {"SKIP_GREMLIN_TESTS": "true"}): - with self.assertRaises(unittest.SkipTest): - TestGremlin.setUpClass() + with mock.patch.dict(os.environ, {"SKIP_GREMLIN_TESTS": "true"}), self.assertRaises(unittest.SkipTest): + TestGremlin.setUpClass() From 8ffd78439b16ee19707ebcbb94078007412a19e8 Mon Sep 17 00:00:00 2001 From: Muawiya-contact Date: Thu, 21 May 2026 15:19:15 +0500 Subject: [PATCH 7/7] refactor: remove dead skip_gremlin_tests flag and simplify lifecycle --- hugegraph-python-client/src/tests/api/test_gremlin.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/hugegraph-python-client/src/tests/api/test_gremlin.py b/hugegraph-python-client/src/tests/api/test_gremlin.py index d47f7bc6..346812b5 100644 --- a/hugegraph-python-client/src/tests/api/test_gremlin.py +++ b/hugegraph-python-client/src/tests/api/test_gremlin.py @@ -28,7 +28,6 @@ class TestGremlin(unittest.TestCase): client = None gremlin = None - skip_gremlin_tests = False @classmethod def setUpClass(cls): @@ -52,12 +51,9 @@ def setUpClass(cls): @classmethod def tearDownClass(cls): - if not cls.skip_gremlin_tests: - cls.client.clear_graph_all_data() + cls.client.clear_graph_all_data() def setUp(self): - if self.skip_gremlin_tests: - self.skipTest("Gremlin endpoint not available in this server") self.client.init_vertices() self.client.init_edges() @@ -111,7 +107,6 @@ class TestGremlinSetupBehavior(unittest.TestCase): def tearDown(self): TestGremlin.client = None TestGremlin.gremlin = None - TestGremlin.skip_gremlin_tests = False def test_set_up_class_reraises_non_probe_failures(self): with mock.patch(f"{TestGremlin.__module__}.ClientUtils") as client_utils_cls: @@ -122,8 +117,6 @@ def test_set_up_class_reraises_non_probe_failures(self): with self.assertRaisesRegex(RuntimeError, "Connection refused during graph cleanup"): TestGremlin.setUpClass() - self.assertFalse(TestGremlin.skip_gremlin_tests) - def test_set_up_class_no_longer_probes_gremlin(self): # After removing the probe, setUpClass should NOT call gremlin.exec at all. with mock.patch(f"{TestGremlin.__module__}.ClientUtils") as client_utils_cls: @@ -139,6 +132,5 @@ def test_set_up_class_skips_when_env_var_set(self): with mock.patch(f"{TestGremlin.__module__}.ClientUtils") as client_utils_cls: client = client_utils_cls.return_value client.gremlin = mock.Mock() - # Ensure the env var causes a SkipTest regardless of client behavior. with mock.patch.dict(os.environ, {"SKIP_GREMLIN_TESTS": "true"}), self.assertRaises(unittest.SkipTest): TestGremlin.setUpClass()