run ruff
This commit is contained in:
@@ -10,27 +10,20 @@ Test Coverage:
|
||||
- Multi-Language Support (3 tests)
|
||||
"""
|
||||
|
||||
import unittest
|
||||
import sys
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
# Add src to path
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'src'))
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "src"))
|
||||
|
||||
from skill_seekers.cli.pattern_recognizer import (
|
||||
SingletonDetector,
|
||||
FactoryDetector,
|
||||
ObserverDetector,
|
||||
StrategyDetector,
|
||||
DecoratorDetector,
|
||||
BuilderDetector,
|
||||
AdapterDetector,
|
||||
CommandDetector,
|
||||
TemplateMethodDetector,
|
||||
ChainOfResponsibilityDetector,
|
||||
PatternRecognizer,
|
||||
LanguageAdapter,
|
||||
PatternInstance
|
||||
ObserverDetector,
|
||||
PatternInstance,
|
||||
PatternRecognizer,
|
||||
SingletonDetector,
|
||||
)
|
||||
|
||||
|
||||
@@ -38,8 +31,8 @@ class TestSingletonDetector(unittest.TestCase):
|
||||
"""Tests for Singleton pattern detection"""
|
||||
|
||||
def setUp(self):
|
||||
self.detector = SingletonDetector(depth='deep')
|
||||
self.recognizer = PatternRecognizer(depth='deep')
|
||||
self.detector = SingletonDetector(depth="deep")
|
||||
self.recognizer = PatternRecognizer(depth="deep")
|
||||
|
||||
def test_surface_detection_by_name(self):
|
||||
"""Test surface detection using class name"""
|
||||
@@ -48,13 +41,13 @@ class DatabaseSingleton:
|
||||
def __init__(self):
|
||||
self.connection = None
|
||||
"""
|
||||
report = self.recognizer.analyze_file('test.py', code, 'Python')
|
||||
report = self.recognizer.analyze_file("test.py", code, "Python")
|
||||
|
||||
self.assertEqual(len(report.patterns), 1)
|
||||
pattern = report.patterns[0]
|
||||
self.assertEqual(pattern.pattern_type, 'Singleton')
|
||||
self.assertEqual(pattern.pattern_type, "Singleton")
|
||||
self.assertGreaterEqual(pattern.confidence, 0.6)
|
||||
self.assertIn('Singleton', pattern.class_name)
|
||||
self.assertIn("Singleton", pattern.class_name)
|
||||
|
||||
def test_deep_detection_with_instance_method(self):
|
||||
"""Test deep detection with getInstance() method"""
|
||||
@@ -66,12 +59,12 @@ class Database:
|
||||
def __init__(self):
|
||||
self._instance = None
|
||||
"""
|
||||
report = self.recognizer.analyze_file('test.py', code, 'Python')
|
||||
report = self.recognizer.analyze_file("test.py", code, "Python")
|
||||
|
||||
# May or may not detect based on getInstance alone
|
||||
# Checking that analysis completes successfully
|
||||
self.assertIsNotNone(report)
|
||||
self.assertEqual(report.language, 'Python')
|
||||
self.assertEqual(report.language, "Python")
|
||||
|
||||
def test_python_singleton_with_new(self):
|
||||
"""Test Python-specific __new__ singleton pattern"""
|
||||
@@ -84,7 +77,7 @@ class Config:
|
||||
cls._instance = super().__new__(cls)
|
||||
return cls._instance
|
||||
"""
|
||||
report = self.recognizer.analyze_file('test.py', code, 'Python')
|
||||
report = self.recognizer.analyze_file("test.py", code, "Python")
|
||||
|
||||
# Detection may vary based on __new__ method signatures from CodeAnalyzer
|
||||
# Main check: analysis completes successfully
|
||||
@@ -107,7 +100,7 @@ public class Singleton {
|
||||
}
|
||||
}
|
||||
"""
|
||||
report = self.recognizer.analyze_file('test.java', code, 'Java')
|
||||
report = self.recognizer.analyze_file("test.java", code, "Java")
|
||||
|
||||
# May detect Singleton based on getInstance method
|
||||
# Since CodeAnalyzer uses regex for Java, detection may vary
|
||||
@@ -118,8 +111,8 @@ class TestFactoryDetector(unittest.TestCase):
|
||||
"""Tests for Factory pattern detection"""
|
||||
|
||||
def setUp(self):
|
||||
self.detector = FactoryDetector(depth='deep')
|
||||
self.recognizer = PatternRecognizer(depth='deep')
|
||||
self.detector = FactoryDetector(depth="deep")
|
||||
self.recognizer = PatternRecognizer(depth="deep")
|
||||
|
||||
def test_surface_detection_by_name(self):
|
||||
"""Test surface detection using class name"""
|
||||
@@ -128,14 +121,14 @@ class CarFactory:
|
||||
def create_car(self, type):
|
||||
pass
|
||||
"""
|
||||
report = self.recognizer.analyze_file('test.py', code, 'Python')
|
||||
report = self.recognizer.analyze_file("test.py", code, "Python")
|
||||
|
||||
patterns = [p for p in report.patterns if p.pattern_type == 'Factory']
|
||||
patterns = [p for p in report.patterns if p.pattern_type == "Factory"]
|
||||
self.assertGreater(len(patterns), 0)
|
||||
pattern = patterns[0]
|
||||
# Confidence may be adjusted by deep detection
|
||||
self.assertGreaterEqual(pattern.confidence, 0.5)
|
||||
self.assertIn('Factory', pattern.class_name)
|
||||
self.assertIn("Factory", pattern.class_name)
|
||||
|
||||
def test_factory_method_detection(self):
|
||||
"""Test detection of create/make methods"""
|
||||
@@ -150,12 +143,12 @@ class VehicleFactory:
|
||||
def make_vehicle(self, specs):
|
||||
return Vehicle(specs)
|
||||
"""
|
||||
report = self.recognizer.analyze_file('test.py', code, 'Python')
|
||||
report = self.recognizer.analyze_file("test.py", code, "Python")
|
||||
|
||||
patterns = [p for p in report.patterns if p.pattern_type == 'Factory']
|
||||
patterns = [p for p in report.patterns if p.pattern_type == "Factory"]
|
||||
self.assertGreater(len(patterns), 0)
|
||||
pattern = patterns[0]
|
||||
self.assertIn('create', ' '.join(pattern.evidence).lower())
|
||||
self.assertIn("create", " ".join(pattern.evidence).lower())
|
||||
|
||||
def test_abstract_factory_multiple_methods(self):
|
||||
"""Test Abstract Factory with multiple creation methods"""
|
||||
@@ -170,9 +163,9 @@ class UIFactory:
|
||||
def create_menu(self):
|
||||
pass
|
||||
"""
|
||||
report = self.recognizer.analyze_file('test.py', code, 'Python')
|
||||
report = self.recognizer.analyze_file("test.py", code, "Python")
|
||||
|
||||
patterns = [p for p in report.patterns if p.pattern_type == 'Factory']
|
||||
patterns = [p for p in report.patterns if p.pattern_type == "Factory"]
|
||||
self.assertGreater(len(patterns), 0)
|
||||
pattern = patterns[0]
|
||||
self.assertGreaterEqual(pattern.confidence, 0.5)
|
||||
@@ -188,9 +181,9 @@ class ShapeFactory:
|
||||
return Square(*args)
|
||||
return None
|
||||
"""
|
||||
report = self.recognizer.analyze_file('test.py', code, 'Python')
|
||||
report = self.recognizer.analyze_file("test.py", code, "Python")
|
||||
|
||||
patterns = [p for p in report.patterns if p.pattern_type == 'Factory']
|
||||
patterns = [p for p in report.patterns if p.pattern_type == "Factory"]
|
||||
self.assertGreater(len(patterns), 0)
|
||||
|
||||
|
||||
@@ -198,8 +191,8 @@ class TestObserverDetector(unittest.TestCase):
|
||||
"""Tests for Observer pattern detection"""
|
||||
|
||||
def setUp(self):
|
||||
self.detector = ObserverDetector(depth='deep')
|
||||
self.recognizer = PatternRecognizer(depth='deep')
|
||||
self.detector = ObserverDetector(depth="deep")
|
||||
self.recognizer = PatternRecognizer(depth="deep")
|
||||
|
||||
def test_observer_triplet_detection(self):
|
||||
"""Test classic attach/detach/notify triplet"""
|
||||
@@ -218,18 +211,14 @@ class Subject:
|
||||
for observer in self.observers:
|
||||
observer.update()
|
||||
"""
|
||||
report = self.recognizer.analyze_file('test.py', code, 'Python')
|
||||
report = self.recognizer.analyze_file("test.py", code, "Python")
|
||||
|
||||
patterns = [p for p in report.patterns if p.pattern_type == 'Observer']
|
||||
patterns = [p for p in report.patterns if p.pattern_type == "Observer"]
|
||||
self.assertGreater(len(patterns), 0)
|
||||
pattern = patterns[0]
|
||||
self.assertGreaterEqual(pattern.confidence, 0.8)
|
||||
evidence_str = ' '.join(pattern.evidence).lower()
|
||||
self.assertTrue(
|
||||
'attach' in evidence_str and
|
||||
'detach' in evidence_str and
|
||||
'notify' in evidence_str
|
||||
)
|
||||
evidence_str = " ".join(pattern.evidence).lower()
|
||||
self.assertTrue("attach" in evidence_str and "detach" in evidence_str and "notify" in evidence_str)
|
||||
|
||||
def test_pubsub_pattern(self):
|
||||
"""Test publish/subscribe variant"""
|
||||
@@ -244,9 +233,9 @@ class EventBus:
|
||||
def publish(self, event, data):
|
||||
pass
|
||||
"""
|
||||
report = self.recognizer.analyze_file('test.py', code, 'Python')
|
||||
report = self.recognizer.analyze_file("test.py", code, "Python")
|
||||
|
||||
patterns = [p for p in report.patterns if p.pattern_type == 'Observer']
|
||||
patterns = [p for p in report.patterns if p.pattern_type == "Observer"]
|
||||
self.assertGreater(len(patterns), 0)
|
||||
|
||||
def test_event_emitter_pattern(self):
|
||||
@@ -262,9 +251,9 @@ class EventEmitter:
|
||||
def emit(self, event, *args):
|
||||
pass
|
||||
"""
|
||||
report = self.recognizer.analyze_file('test.py', code, 'Python')
|
||||
report = self.recognizer.analyze_file("test.py", code, "Python")
|
||||
|
||||
patterns = [p for p in report.patterns if p.pattern_type == 'Observer']
|
||||
patterns = [p for p in report.patterns if p.pattern_type == "Observer"]
|
||||
self.assertGreater(len(patterns), 0)
|
||||
|
||||
|
||||
@@ -272,7 +261,7 @@ class TestPatternRecognizerIntegration(unittest.TestCase):
|
||||
"""Integration tests for PatternRecognizer"""
|
||||
|
||||
def setUp(self):
|
||||
self.recognizer = PatternRecognizer(depth='deep')
|
||||
self.recognizer = PatternRecognizer(depth="deep")
|
||||
|
||||
def test_analyze_singleton_code(self):
|
||||
"""Test end-to-end Singleton analysis"""
|
||||
@@ -288,10 +277,10 @@ class ConfigManager:
|
||||
def getInstance(self):
|
||||
return self._instance
|
||||
"""
|
||||
report = self.recognizer.analyze_file('config.py', code, 'Python')
|
||||
report = self.recognizer.analyze_file("config.py", code, "Python")
|
||||
|
||||
self.assertEqual(report.file_path, 'config.py')
|
||||
self.assertEqual(report.language, 'Python')
|
||||
self.assertEqual(report.file_path, "config.py")
|
||||
self.assertEqual(report.language, "Python")
|
||||
self.assertGreater(len(report.patterns), 0)
|
||||
self.assertGreater(report.total_classes, 0)
|
||||
|
||||
@@ -306,9 +295,9 @@ class AnimalFactory:
|
||||
return Cat()
|
||||
return None
|
||||
"""
|
||||
report = self.recognizer.analyze_file('factory.py', code, 'Python')
|
||||
report = self.recognizer.analyze_file("factory.py", code, "Python")
|
||||
|
||||
patterns = [p for p in report.patterns if p.pattern_type == 'Factory']
|
||||
patterns = [p for p in report.patterns if p.pattern_type == "Factory"]
|
||||
self.assertGreater(len(patterns), 0)
|
||||
|
||||
def test_analyze_observer_code(self):
|
||||
@@ -328,9 +317,9 @@ class WeatherStation:
|
||||
for obs in self.observers:
|
||||
obs.update(self.temperature)
|
||||
"""
|
||||
report = self.recognizer.analyze_file('weather.py', code, 'Python')
|
||||
report = self.recognizer.analyze_file("weather.py", code, "Python")
|
||||
|
||||
patterns = [p for p in report.patterns if p.pattern_type == 'Observer']
|
||||
patterns = [p for p in report.patterns if p.pattern_type == "Observer"]
|
||||
self.assertGreater(len(patterns), 0)
|
||||
|
||||
def test_pattern_report_summary(self):
|
||||
@@ -346,7 +335,7 @@ class LoggerFactory:
|
||||
def create_logger(self, type):
|
||||
return Logger(type)
|
||||
"""
|
||||
report = self.recognizer.analyze_file('logging.py', code, 'Python')
|
||||
report = self.recognizer.analyze_file("logging.py", code, "Python")
|
||||
|
||||
summary = report.get_summary()
|
||||
self.assertIsInstance(summary, dict)
|
||||
@@ -361,7 +350,7 @@ class TestMultiLanguageSupport(unittest.TestCase):
|
||||
"""Tests for multi-language pattern detection"""
|
||||
|
||||
def setUp(self):
|
||||
self.recognizer = PatternRecognizer(depth='deep')
|
||||
self.recognizer = PatternRecognizer(depth="deep")
|
||||
|
||||
def test_python_patterns(self):
|
||||
"""Test Python-specific patterns"""
|
||||
@@ -374,12 +363,12 @@ class DatabaseConnection:
|
||||
cls._instance = super().__new__(cls)
|
||||
return cls._instance
|
||||
"""
|
||||
report = self.recognizer.analyze_file('db.py', code, 'Python')
|
||||
report = self.recognizer.analyze_file("db.py", code, "Python")
|
||||
|
||||
# Detection depends on CodeAnalyzer's ability to parse __new__ method
|
||||
# Main check: analysis completes successfully
|
||||
self.assertIsNotNone(report)
|
||||
self.assertEqual(report.language, 'Python')
|
||||
self.assertEqual(report.language, "Python")
|
||||
|
||||
def test_javascript_patterns(self):
|
||||
"""Test JavaScript-specific patterns"""
|
||||
@@ -402,7 +391,7 @@ const singleton = (function() {
|
||||
})();
|
||||
"""
|
||||
# Note: CodeAnalyzer uses regex for JavaScript, so detection may be limited
|
||||
report = self.recognizer.analyze_file('app.js', code, 'JavaScript')
|
||||
report = self.recognizer.analyze_file("app.js", code, "JavaScript")
|
||||
self.assertIsNotNone(report)
|
||||
|
||||
def test_java_patterns(self):
|
||||
@@ -421,7 +410,7 @@ public class Logger {
|
||||
}
|
||||
}
|
||||
"""
|
||||
report = self.recognizer.analyze_file('Logger.java', code, 'Java')
|
||||
report = self.recognizer.analyze_file("Logger.java", code, "Java")
|
||||
self.assertIsNotNone(report)
|
||||
|
||||
|
||||
@@ -429,7 +418,7 @@ class TestExtendedPatternDetectors(unittest.TestCase):
|
||||
"""Tests for extended pattern detectors (Builder, Adapter, Command, etc.)"""
|
||||
|
||||
def setUp(self):
|
||||
self.recognizer = PatternRecognizer(depth='deep')
|
||||
self.recognizer = PatternRecognizer(depth="deep")
|
||||
|
||||
def test_builder_pattern(self):
|
||||
"""Test Builder pattern detection"""
|
||||
@@ -449,9 +438,9 @@ class QueryBuilder:
|
||||
def build(self):
|
||||
return Query(self.query)
|
||||
"""
|
||||
report = self.recognizer.analyze_file('query.py', code, 'Python')
|
||||
report = self.recognizer.analyze_file("query.py", code, "Python")
|
||||
|
||||
patterns = [p for p in report.patterns if p.pattern_type == 'Builder']
|
||||
patterns = [p for p in report.patterns if p.pattern_type == "Builder"]
|
||||
self.assertGreater(len(patterns), 0)
|
||||
|
||||
def test_adapter_pattern(self):
|
||||
@@ -467,9 +456,9 @@ class DatabaseAdapter:
|
||||
def connect(self):
|
||||
return self.adaptee.open_connection()
|
||||
"""
|
||||
report = self.recognizer.analyze_file('adapter.py', code, 'Python')
|
||||
report = self.recognizer.analyze_file("adapter.py", code, "Python")
|
||||
|
||||
patterns = [p for p in report.patterns if p.pattern_type == 'Adapter']
|
||||
patterns = [p for p in report.patterns if p.pattern_type == "Adapter"]
|
||||
self.assertGreater(len(patterns), 0)
|
||||
|
||||
def test_command_pattern(self):
|
||||
@@ -485,9 +474,9 @@ class SaveCommand:
|
||||
def undo(self):
|
||||
self.receiver.revert()
|
||||
"""
|
||||
report = self.recognizer.analyze_file('command.py', code, 'Python')
|
||||
report = self.recognizer.analyze_file("command.py", code, "Python")
|
||||
|
||||
patterns = [p for p in report.patterns if p.pattern_type == 'Command']
|
||||
patterns = [p for p in report.patterns if p.pattern_type == "Command"]
|
||||
self.assertGreater(len(patterns), 0)
|
||||
|
||||
|
||||
@@ -497,38 +486,38 @@ class TestLanguageAdapter(unittest.TestCase):
|
||||
def test_python_decorator_boost(self):
|
||||
"""Test Python @decorator syntax boost"""
|
||||
pattern = PatternInstance(
|
||||
pattern_type='Decorator',
|
||||
category='Structural',
|
||||
pattern_type="Decorator",
|
||||
category="Structural",
|
||||
confidence=0.6,
|
||||
location='test.py',
|
||||
class_name='LogDecorator',
|
||||
evidence=['Uses @decorator syntax']
|
||||
location="test.py",
|
||||
class_name="LogDecorator",
|
||||
evidence=["Uses @decorator syntax"],
|
||||
)
|
||||
|
||||
adapted = LanguageAdapter.adapt_for_language(pattern, 'Python')
|
||||
adapted = LanguageAdapter.adapt_for_language(pattern, "Python")
|
||||
self.assertGreater(adapted.confidence, 0.6)
|
||||
self.assertIn('Python @decorator', ' '.join(adapted.evidence))
|
||||
self.assertIn("Python @decorator", " ".join(adapted.evidence))
|
||||
|
||||
def test_javascript_module_pattern(self):
|
||||
"""Test JavaScript module pattern boost"""
|
||||
pattern = PatternInstance(
|
||||
pattern_type='Singleton',
|
||||
category='Creational',
|
||||
pattern_type="Singleton",
|
||||
category="Creational",
|
||||
confidence=0.5,
|
||||
location='app.js',
|
||||
class_name='App',
|
||||
evidence=['Has getInstance', 'module pattern detected']
|
||||
location="app.js",
|
||||
class_name="App",
|
||||
evidence=["Has getInstance", "module pattern detected"],
|
||||
)
|
||||
|
||||
adapted = LanguageAdapter.adapt_for_language(pattern, 'JavaScript')
|
||||
adapted = LanguageAdapter.adapt_for_language(pattern, "JavaScript")
|
||||
self.assertGreater(adapted.confidence, 0.5)
|
||||
|
||||
def test_no_pattern_returns_none(self):
|
||||
"""Test None input returns None"""
|
||||
result = LanguageAdapter.adapt_for_language(None, 'Python')
|
||||
result = LanguageAdapter.adapt_for_language(None, "Python")
|
||||
self.assertIsNone(result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
# Run tests with verbose output
|
||||
unittest.main(verbosity=2)
|
||||
|
||||
Reference in New Issue
Block a user