Skip to content

Commit 6c09519

Browse files
committed
test(services): Add method to check for duplicate method implementations in service class
1 parent 9346f60 commit 6c09519

File tree

1 file changed

+67
-0
lines changed

1 file changed

+67
-0
lines changed

tests/services/base_service_test.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import os
44
import inspect
5+
import ast
56
from unittest.mock import Mock, patch
67
from lxml import etree
78
from typing import Dict, List, Any, Optional, Type
@@ -104,6 +105,72 @@ def test_import(self):
104105
"""Test that service class can be imported."""
105106
assert self.SERVICE_CLASS is not None
106107

108+
def test_no_duplicate_methods(self):
109+
"""Test that there are no duplicate method implementations in service class."""
110+
if not self.SERVICE_CLASS:
111+
return
112+
113+
# Get the source file of the service class
114+
source_file = inspect.getsourcefile(self.SERVICE_CLASS)
115+
if not source_file:
116+
return
117+
118+
# Parse the source file
119+
with open(source_file, "r", encoding="utf-8") as f:
120+
source_code = f.read()
121+
122+
tree = ast.parse(source_code)
123+
124+
# Find the class definition
125+
class_node = None
126+
for node in ast.walk(tree):
127+
if (
128+
isinstance(node, ast.ClassDef)
129+
and node.name == self.SERVICE_CLASS.__name__
130+
):
131+
class_node = node
132+
break
133+
134+
if not class_node:
135+
return
136+
137+
# Collect all method names defined in the class
138+
method_names = []
139+
method_line_numbers = {}
140+
141+
for item in class_node.body:
142+
if isinstance(item, ast.FunctionDef):
143+
method_name = item.name
144+
# Skip private methods and __init__
145+
if method_name.startswith("_") or method_name == "__init__":
146+
continue
147+
148+
# Skip helper methods
149+
if method_name in ["type", "desc", "operations"]:
150+
continue
151+
152+
method_names.append(method_name)
153+
154+
# Track line numbers for better error reporting
155+
if method_name not in method_line_numbers:
156+
method_line_numbers[method_name] = []
157+
method_line_numbers[method_name].append(item.lineno)
158+
159+
# Find duplicates
160+
from collections import Counter
161+
162+
method_counts = Counter(method_names)
163+
duplicates = [
164+
f"{name}: defined {count} times at lines {method_line_numbers[name]}"
165+
for name, count in method_counts.items()
166+
if count > 1
167+
]
168+
169+
assert not duplicates, (
170+
f"Duplicate method implementations found in {self.SERVICE_CLASS.__name__}:\n"
171+
+ "\n".join(duplicates)
172+
)
173+
107174
def test_wsdl_operations_not_empty(self):
108175
"""Test that WSDL operations are successfully parsed and not empty."""
109176
wsdl_operations = self.get_wsdl_operations()

0 commit comments

Comments
 (0)