mirror of
https://github.com/SuperClaude-Org/SuperClaude_Framework.git
synced 2025-12-29 16:16:08 +00:00
476 lines
20 KiB
Python
476 lines
20 KiB
Python
|
|
#!/usr/bin/env python3
|
||
|
|
"""
|
||
|
|
Comprehensive tests for framework_logic.py
|
||
|
|
|
||
|
|
Tests all core functionality including:
|
||
|
|
- RULES.md compliance validation
|
||
|
|
- PRINCIPLES.md application
|
||
|
|
- ORCHESTRATOR.md decision logic
|
||
|
|
- Risk assessment and complexity scoring
|
||
|
|
- Performance estimation and optimization
|
||
|
|
"""
|
||
|
|
|
||
|
|
import unittest
|
||
|
|
import sys
|
||
|
|
from pathlib import Path
|
||
|
|
|
||
|
|
# Add the shared directory to path for imports
|
||
|
|
sys.path.insert(0, str(Path(__file__).parent.parent))
|
||
|
|
|
||
|
|
from framework_logic import (
|
||
|
|
FrameworkLogic, OperationType, RiskLevel, OperationContext,
|
||
|
|
ValidationResult
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
class TestFrameworkLogic(unittest.TestCase):
|
||
|
|
"""Comprehensive tests for FrameworkLogic."""
|
||
|
|
|
||
|
|
def setUp(self):
|
||
|
|
"""Set up test environment."""
|
||
|
|
self.framework = FrameworkLogic()
|
||
|
|
|
||
|
|
# Create test contexts
|
||
|
|
self.simple_context = OperationContext(
|
||
|
|
operation_type=OperationType.READ,
|
||
|
|
file_count=1,
|
||
|
|
directory_count=1,
|
||
|
|
has_tests=False,
|
||
|
|
is_production=False,
|
||
|
|
user_expertise='intermediate',
|
||
|
|
project_type='web',
|
||
|
|
complexity_score=0.2,
|
||
|
|
risk_level=RiskLevel.LOW
|
||
|
|
)
|
||
|
|
|
||
|
|
self.complex_context = OperationContext(
|
||
|
|
operation_type=OperationType.REFACTOR,
|
||
|
|
file_count=15,
|
||
|
|
directory_count=5,
|
||
|
|
has_tests=True,
|
||
|
|
is_production=True,
|
||
|
|
user_expertise='expert',
|
||
|
|
project_type='api',
|
||
|
|
complexity_score=0.8,
|
||
|
|
risk_level=RiskLevel.HIGH
|
||
|
|
)
|
||
|
|
|
||
|
|
def test_read_before_write_rule(self):
|
||
|
|
"""Test RULES.md: Always use Read tool before Write or Edit operations."""
|
||
|
|
# Write and Edit operations should require read
|
||
|
|
write_context = OperationContext(
|
||
|
|
operation_type=OperationType.WRITE,
|
||
|
|
file_count=1, directory_count=1, has_tests=False,
|
||
|
|
is_production=False, user_expertise='beginner',
|
||
|
|
project_type='web', complexity_score=0.3, risk_level=RiskLevel.LOW
|
||
|
|
)
|
||
|
|
edit_context = OperationContext(
|
||
|
|
operation_type=OperationType.EDIT,
|
||
|
|
file_count=1, directory_count=1, has_tests=False,
|
||
|
|
is_production=False, user_expertise='beginner',
|
||
|
|
project_type='web', complexity_score=0.3, risk_level=RiskLevel.LOW
|
||
|
|
)
|
||
|
|
|
||
|
|
self.assertTrue(self.framework.should_use_read_before_write(write_context))
|
||
|
|
self.assertTrue(self.framework.should_use_read_before_write(edit_context))
|
||
|
|
|
||
|
|
# Read operations should not require read
|
||
|
|
self.assertFalse(self.framework.should_use_read_before_write(self.simple_context))
|
||
|
|
|
||
|
|
def test_complexity_score_calculation(self):
|
||
|
|
"""Test complexity score calculation algorithm."""
|
||
|
|
# Simple operation
|
||
|
|
simple_data = {
|
||
|
|
'file_count': 1,
|
||
|
|
'directory_count': 1,
|
||
|
|
'operation_type': 'read',
|
||
|
|
'multi_language': False,
|
||
|
|
'framework_changes': False
|
||
|
|
}
|
||
|
|
simple_score = self.framework.calculate_complexity_score(simple_data)
|
||
|
|
self.assertLess(simple_score, 0.3)
|
||
|
|
|
||
|
|
# Complex operation
|
||
|
|
complex_data = {
|
||
|
|
'file_count': 20,
|
||
|
|
'directory_count': 5,
|
||
|
|
'operation_type': 'refactor',
|
||
|
|
'multi_language': True,
|
||
|
|
'framework_changes': True
|
||
|
|
}
|
||
|
|
complex_score = self.framework.calculate_complexity_score(complex_data)
|
||
|
|
self.assertGreater(complex_score, 0.7)
|
||
|
|
|
||
|
|
# Score should be capped at 1.0
|
||
|
|
extreme_data = {
|
||
|
|
'file_count': 1000,
|
||
|
|
'directory_count': 100,
|
||
|
|
'operation_type': 'system-wide',
|
||
|
|
'multi_language': True,
|
||
|
|
'framework_changes': True
|
||
|
|
}
|
||
|
|
extreme_score = self.framework.calculate_complexity_score(extreme_data)
|
||
|
|
self.assertEqual(extreme_score, 1.0)
|
||
|
|
|
||
|
|
def test_risk_assessment(self):
|
||
|
|
"""Test risk level assessment logic."""
|
||
|
|
# Production context should be high risk
|
||
|
|
prod_context = OperationContext(
|
||
|
|
operation_type=OperationType.DEPLOY,
|
||
|
|
file_count=5, directory_count=2, has_tests=True,
|
||
|
|
is_production=True, user_expertise='expert',
|
||
|
|
project_type='api', complexity_score=0.5, risk_level=RiskLevel.MEDIUM
|
||
|
|
)
|
||
|
|
risk = self.framework.assess_risk_level(prod_context)
|
||
|
|
self.assertEqual(risk, RiskLevel.HIGH)
|
||
|
|
|
||
|
|
# High complexity should be high risk
|
||
|
|
high_complexity_context = OperationContext(
|
||
|
|
operation_type=OperationType.BUILD,
|
||
|
|
file_count=5, directory_count=2, has_tests=False,
|
||
|
|
is_production=False, user_expertise='intermediate',
|
||
|
|
project_type='web', complexity_score=0.8, risk_level=RiskLevel.LOW
|
||
|
|
)
|
||
|
|
risk = self.framework.assess_risk_level(high_complexity_context)
|
||
|
|
self.assertEqual(risk, RiskLevel.HIGH)
|
||
|
|
|
||
|
|
# Many files should be medium risk
|
||
|
|
many_files_context = OperationContext(
|
||
|
|
operation_type=OperationType.EDIT,
|
||
|
|
file_count=15, directory_count=2, has_tests=False,
|
||
|
|
is_production=False, user_expertise='intermediate',
|
||
|
|
project_type='web', complexity_score=0.3, risk_level=RiskLevel.LOW
|
||
|
|
)
|
||
|
|
risk = self.framework.assess_risk_level(many_files_context)
|
||
|
|
self.assertEqual(risk, RiskLevel.MEDIUM)
|
||
|
|
|
||
|
|
# Simple operations should be low risk
|
||
|
|
risk = self.framework.assess_risk_level(self.simple_context)
|
||
|
|
self.assertEqual(risk, RiskLevel.LOW)
|
||
|
|
|
||
|
|
def test_validation_enablement(self):
|
||
|
|
"""Test when validation should be enabled."""
|
||
|
|
# High risk operations should enable validation
|
||
|
|
self.assertTrue(self.framework.should_enable_validation(self.complex_context))
|
||
|
|
|
||
|
|
# Production operations should enable validation
|
||
|
|
prod_context = OperationContext(
|
||
|
|
operation_type=OperationType.WRITE,
|
||
|
|
file_count=1, directory_count=1, has_tests=False,
|
||
|
|
is_production=True, user_expertise='beginner',
|
||
|
|
project_type='web', complexity_score=0.2, risk_level=RiskLevel.LOW
|
||
|
|
)
|
||
|
|
self.assertTrue(self.framework.should_enable_validation(prod_context))
|
||
|
|
|
||
|
|
# Deploy operations should enable validation
|
||
|
|
deploy_context = OperationContext(
|
||
|
|
operation_type=OperationType.DEPLOY,
|
||
|
|
file_count=1, directory_count=1, has_tests=False,
|
||
|
|
is_production=False, user_expertise='expert',
|
||
|
|
project_type='web', complexity_score=0.2, risk_level=RiskLevel.LOW
|
||
|
|
)
|
||
|
|
self.assertTrue(self.framework.should_enable_validation(deploy_context))
|
||
|
|
|
||
|
|
# Simple operations should not require validation
|
||
|
|
self.assertFalse(self.framework.should_enable_validation(self.simple_context))
|
||
|
|
|
||
|
|
def test_delegation_logic(self):
|
||
|
|
"""Test delegation decision logic."""
|
||
|
|
# Multiple files should trigger delegation
|
||
|
|
should_delegate, strategy = self.framework.should_enable_delegation(self.complex_context)
|
||
|
|
self.assertTrue(should_delegate)
|
||
|
|
self.assertEqual(strategy, "files")
|
||
|
|
|
||
|
|
# Multiple directories should trigger delegation
|
||
|
|
multi_dir_context = OperationContext(
|
||
|
|
operation_type=OperationType.ANALYZE,
|
||
|
|
file_count=2, directory_count=4, has_tests=False,
|
||
|
|
is_production=False, user_expertise='intermediate',
|
||
|
|
project_type='web', complexity_score=0.3, risk_level=RiskLevel.LOW
|
||
|
|
)
|
||
|
|
should_delegate, strategy = self.framework.should_enable_delegation(multi_dir_context)
|
||
|
|
self.assertTrue(should_delegate)
|
||
|
|
self.assertEqual(strategy, "folders")
|
||
|
|
|
||
|
|
# High complexity should trigger auto delegation
|
||
|
|
high_complexity_context = OperationContext(
|
||
|
|
operation_type=OperationType.BUILD,
|
||
|
|
file_count=2, directory_count=1, has_tests=False,
|
||
|
|
is_production=False, user_expertise='intermediate',
|
||
|
|
project_type='web', complexity_score=0.7, risk_level=RiskLevel.MEDIUM
|
||
|
|
)
|
||
|
|
should_delegate, strategy = self.framework.should_enable_delegation(high_complexity_context)
|
||
|
|
self.assertTrue(should_delegate)
|
||
|
|
self.assertEqual(strategy, "auto")
|
||
|
|
|
||
|
|
# Simple operations should not require delegation
|
||
|
|
should_delegate, strategy = self.framework.should_enable_delegation(self.simple_context)
|
||
|
|
self.assertFalse(should_delegate)
|
||
|
|
self.assertEqual(strategy, "none")
|
||
|
|
|
||
|
|
def test_operation_validation(self):
|
||
|
|
"""Test operation validation against PRINCIPLES.md."""
|
||
|
|
# Valid operation with all requirements
|
||
|
|
valid_operation = {
|
||
|
|
'operation_type': 'write',
|
||
|
|
'evidence': 'User explicitly requested file creation',
|
||
|
|
'has_error_handling': True,
|
||
|
|
'affects_logic': True,
|
||
|
|
'has_tests': True,
|
||
|
|
'is_public_api': False,
|
||
|
|
'handles_user_input': False
|
||
|
|
}
|
||
|
|
result = self.framework.validate_operation(valid_operation)
|
||
|
|
self.assertTrue(result.is_valid)
|
||
|
|
self.assertEqual(len(result.issues), 0)
|
||
|
|
self.assertGreaterEqual(result.quality_score, 0.7)
|
||
|
|
|
||
|
|
# Invalid operation missing error handling
|
||
|
|
invalid_operation = {
|
||
|
|
'operation_type': 'write',
|
||
|
|
'evidence': 'User requested',
|
||
|
|
'has_error_handling': False,
|
||
|
|
'affects_logic': True,
|
||
|
|
'has_tests': False,
|
||
|
|
'is_public_api': True,
|
||
|
|
'has_documentation': False,
|
||
|
|
'handles_user_input': True,
|
||
|
|
'has_input_validation': False
|
||
|
|
}
|
||
|
|
result = self.framework.validate_operation(invalid_operation)
|
||
|
|
self.assertFalse(result.is_valid)
|
||
|
|
self.assertGreater(len(result.issues), 0)
|
||
|
|
self.assertLess(result.quality_score, 0.7)
|
||
|
|
|
||
|
|
# Check specific validation issues
|
||
|
|
issue_texts = ' '.join(result.issues).lower()
|
||
|
|
self.assertIn('error handling', issue_texts)
|
||
|
|
self.assertIn('input', issue_texts)
|
||
|
|
|
||
|
|
warning_texts = ' '.join(result.warnings).lower()
|
||
|
|
self.assertIn('tests', warning_texts)
|
||
|
|
self.assertIn('documentation', warning_texts)
|
||
|
|
|
||
|
|
def test_thinking_mode_determination(self):
|
||
|
|
"""Test thinking mode determination based on complexity."""
|
||
|
|
# Very high complexity should trigger ultrathink
|
||
|
|
ultra_context = OperationContext(
|
||
|
|
operation_type=OperationType.REFACTOR,
|
||
|
|
file_count=20, directory_count=5, has_tests=True,
|
||
|
|
is_production=True, user_expertise='expert',
|
||
|
|
project_type='system', complexity_score=0.85, risk_level=RiskLevel.HIGH
|
||
|
|
)
|
||
|
|
mode = self.framework.determine_thinking_mode(ultra_context)
|
||
|
|
self.assertEqual(mode, "--ultrathink")
|
||
|
|
|
||
|
|
# High complexity should trigger think-hard
|
||
|
|
hard_context = OperationContext(
|
||
|
|
operation_type=OperationType.BUILD,
|
||
|
|
file_count=10, directory_count=3, has_tests=True,
|
||
|
|
is_production=False, user_expertise='intermediate',
|
||
|
|
project_type='web', complexity_score=0.65, risk_level=RiskLevel.MEDIUM
|
||
|
|
)
|
||
|
|
mode = self.framework.determine_thinking_mode(hard_context)
|
||
|
|
self.assertEqual(mode, "--think-hard")
|
||
|
|
|
||
|
|
# Medium complexity should trigger think
|
||
|
|
medium_context = OperationContext(
|
||
|
|
operation_type=OperationType.ANALYZE,
|
||
|
|
file_count=5, directory_count=2, has_tests=False,
|
||
|
|
is_production=False, user_expertise='intermediate',
|
||
|
|
project_type='web', complexity_score=0.4, risk_level=RiskLevel.LOW
|
||
|
|
)
|
||
|
|
mode = self.framework.determine_thinking_mode(medium_context)
|
||
|
|
self.assertEqual(mode, "--think")
|
||
|
|
|
||
|
|
# Low complexity should not trigger thinking mode
|
||
|
|
mode = self.framework.determine_thinking_mode(self.simple_context)
|
||
|
|
self.assertIsNone(mode)
|
||
|
|
|
||
|
|
def test_efficiency_mode_enablement(self):
|
||
|
|
"""Test token efficiency mode enablement logic."""
|
||
|
|
# High resource usage should enable efficiency mode
|
||
|
|
high_resource_session = {
|
||
|
|
'resource_usage_percent': 80,
|
||
|
|
'conversation_length': 50,
|
||
|
|
'user_requests_brevity': False
|
||
|
|
}
|
||
|
|
self.assertTrue(self.framework.should_enable_efficiency_mode(high_resource_session))
|
||
|
|
|
||
|
|
# Long conversation should enable efficiency mode
|
||
|
|
long_conversation_session = {
|
||
|
|
'resource_usage_percent': 60,
|
||
|
|
'conversation_length': 150,
|
||
|
|
'user_requests_brevity': False
|
||
|
|
}
|
||
|
|
self.assertTrue(self.framework.should_enable_efficiency_mode(long_conversation_session))
|
||
|
|
|
||
|
|
# User requesting brevity should enable efficiency mode
|
||
|
|
brevity_request_session = {
|
||
|
|
'resource_usage_percent': 50,
|
||
|
|
'conversation_length': 30,
|
||
|
|
'user_requests_brevity': True
|
||
|
|
}
|
||
|
|
self.assertTrue(self.framework.should_enable_efficiency_mode(brevity_request_session))
|
||
|
|
|
||
|
|
# Normal session should not enable efficiency mode
|
||
|
|
normal_session = {
|
||
|
|
'resource_usage_percent': 40,
|
||
|
|
'conversation_length': 20,
|
||
|
|
'user_requests_brevity': False
|
||
|
|
}
|
||
|
|
self.assertFalse(self.framework.should_enable_efficiency_mode(normal_session))
|
||
|
|
|
||
|
|
def test_quality_gates_selection(self):
|
||
|
|
"""Test quality gate selection for different operations."""
|
||
|
|
# All operations should have syntax validation
|
||
|
|
gates = self.framework.get_quality_gates(self.simple_context)
|
||
|
|
self.assertIn('syntax_validation', gates)
|
||
|
|
|
||
|
|
# Write/Edit operations should have additional gates
|
||
|
|
write_context = OperationContext(
|
||
|
|
operation_type=OperationType.WRITE,
|
||
|
|
file_count=1, directory_count=1, has_tests=False,
|
||
|
|
is_production=False, user_expertise='intermediate',
|
||
|
|
project_type='web', complexity_score=0.3, risk_level=RiskLevel.LOW
|
||
|
|
)
|
||
|
|
gates = self.framework.get_quality_gates(write_context)
|
||
|
|
self.assertIn('syntax_validation', gates)
|
||
|
|
self.assertIn('type_analysis', gates)
|
||
|
|
self.assertIn('code_quality', gates)
|
||
|
|
|
||
|
|
# High-risk operations should have security and performance gates
|
||
|
|
gates = self.framework.get_quality_gates(self.complex_context)
|
||
|
|
self.assertIn('security_assessment', gates)
|
||
|
|
self.assertIn('performance_analysis', gates)
|
||
|
|
|
||
|
|
# Operations with tests should include test validation
|
||
|
|
test_context = OperationContext(
|
||
|
|
operation_type=OperationType.BUILD,
|
||
|
|
file_count=5, directory_count=2, has_tests=True,
|
||
|
|
is_production=False, user_expertise='expert',
|
||
|
|
project_type='api', complexity_score=0.5, risk_level=RiskLevel.MEDIUM
|
||
|
|
)
|
||
|
|
gates = self.framework.get_quality_gates(test_context)
|
||
|
|
self.assertIn('test_validation', gates)
|
||
|
|
|
||
|
|
# Deploy operations should have integration testing
|
||
|
|
deploy_context = OperationContext(
|
||
|
|
operation_type=OperationType.DEPLOY,
|
||
|
|
file_count=3, directory_count=1, has_tests=True,
|
||
|
|
is_production=True, user_expertise='expert',
|
||
|
|
project_type='web', complexity_score=0.4, risk_level=RiskLevel.HIGH
|
||
|
|
)
|
||
|
|
gates = self.framework.get_quality_gates(deploy_context)
|
||
|
|
self.assertIn('integration_testing', gates)
|
||
|
|
self.assertIn('deployment_validation', gates)
|
||
|
|
|
||
|
|
def test_performance_impact_estimation(self):
|
||
|
|
"""Test performance impact estimation."""
|
||
|
|
# Simple operation should have low estimated time
|
||
|
|
simple_estimate = self.framework.estimate_performance_impact(self.simple_context)
|
||
|
|
self.assertLess(simple_estimate['estimated_time_ms'], 300)
|
||
|
|
self.assertEqual(simple_estimate['performance_risk'], 'low')
|
||
|
|
self.assertEqual(len(simple_estimate['suggested_optimizations']), 0)
|
||
|
|
|
||
|
|
# Complex operation should have higher estimated time and optimizations
|
||
|
|
complex_estimate = self.framework.estimate_performance_impact(self.complex_context)
|
||
|
|
self.assertGreater(complex_estimate['estimated_time_ms'], 400)
|
||
|
|
self.assertGreater(len(complex_estimate['suggested_optimizations']), 2)
|
||
|
|
|
||
|
|
# Should suggest appropriate optimizations
|
||
|
|
optimizations = complex_estimate['suggested_optimizations']
|
||
|
|
opt_text = ' '.join(optimizations).lower()
|
||
|
|
self.assertIn('parallel', opt_text)
|
||
|
|
self.assertIn('delegation', opt_text)
|
||
|
|
|
||
|
|
# Very high estimated time should be high risk
|
||
|
|
if complex_estimate['estimated_time_ms'] > 1000:
|
||
|
|
self.assertEqual(complex_estimate['performance_risk'], 'high')
|
||
|
|
|
||
|
|
def test_superclaude_principles_application(self):
|
||
|
|
"""Test application of SuperClaude core principles."""
|
||
|
|
# Test Evidence > assumptions principle
|
||
|
|
assumption_heavy_data = {
|
||
|
|
'operation_type': 'analyze',
|
||
|
|
'assumptions': ['This should work', 'Users will like it'],
|
||
|
|
'evidence': None
|
||
|
|
}
|
||
|
|
enhanced = self.framework.apply_superclaude_principles(assumption_heavy_data)
|
||
|
|
self.assertIn('recommendations', enhanced)
|
||
|
|
rec_text = ' '.join(enhanced['recommendations']).lower()
|
||
|
|
self.assertIn('evidence', rec_text)
|
||
|
|
|
||
|
|
# Test Code > documentation principle
|
||
|
|
doc_heavy_data = {
|
||
|
|
'operation_type': 'document',
|
||
|
|
'has_working_code': False
|
||
|
|
}
|
||
|
|
enhanced = self.framework.apply_superclaude_principles(doc_heavy_data)
|
||
|
|
self.assertIn('warnings', enhanced)
|
||
|
|
warning_text = ' '.join(enhanced['warnings']).lower()
|
||
|
|
self.assertIn('working code', warning_text)
|
||
|
|
|
||
|
|
# Test Efficiency > verbosity principle
|
||
|
|
verbose_data = {
|
||
|
|
'operation_type': 'generate',
|
||
|
|
'output_length': 2000,
|
||
|
|
'justification_for_length': None
|
||
|
|
}
|
||
|
|
enhanced = self.framework.apply_superclaude_principles(verbose_data)
|
||
|
|
self.assertIn('efficiency_suggestions', enhanced)
|
||
|
|
eff_text = ' '.join(enhanced['efficiency_suggestions']).lower()
|
||
|
|
self.assertIn('token efficiency', eff_text)
|
||
|
|
|
||
|
|
def test_performance_targets_loading(self):
|
||
|
|
"""Test that performance targets are loaded correctly."""
|
||
|
|
# Should have performance targets loaded
|
||
|
|
self.assertIsInstance(self.framework.performance_targets, dict)
|
||
|
|
|
||
|
|
# Should have hook-specific targets (with defaults if config not available)
|
||
|
|
expected_targets = [
|
||
|
|
'session_start_ms',
|
||
|
|
'tool_routing_ms',
|
||
|
|
'validation_ms',
|
||
|
|
'compression_ms'
|
||
|
|
]
|
||
|
|
|
||
|
|
for target in expected_targets:
|
||
|
|
self.assertIn(target, self.framework.performance_targets)
|
||
|
|
self.assertIsInstance(self.framework.performance_targets[target], (int, float))
|
||
|
|
self.assertGreater(self.framework.performance_targets[target], 0)
|
||
|
|
|
||
|
|
def test_edge_cases_and_error_handling(self):
|
||
|
|
"""Test edge cases and error handling."""
|
||
|
|
# Empty operation data
|
||
|
|
empty_score = self.framework.calculate_complexity_score({})
|
||
|
|
self.assertGreaterEqual(empty_score, 0.0)
|
||
|
|
self.assertLessEqual(empty_score, 1.0)
|
||
|
|
|
||
|
|
# Negative file counts (shouldn't happen but should be handled)
|
||
|
|
negative_data = {
|
||
|
|
'file_count': -1,
|
||
|
|
'directory_count': -1,
|
||
|
|
'operation_type': 'unknown'
|
||
|
|
}
|
||
|
|
negative_score = self.framework.calculate_complexity_score(negative_data)
|
||
|
|
self.assertGreaterEqual(negative_score, 0.0)
|
||
|
|
|
||
|
|
# Very large file counts
|
||
|
|
large_data = {
|
||
|
|
'file_count': 1000000,
|
||
|
|
'directory_count': 10000,
|
||
|
|
'operation_type': 'system-wide'
|
||
|
|
}
|
||
|
|
large_score = self.framework.calculate_complexity_score(large_data)
|
||
|
|
self.assertEqual(large_score, 1.0) # Should be capped
|
||
|
|
|
||
|
|
# Empty validation operation
|
||
|
|
empty_validation = self.framework.validate_operation({})
|
||
|
|
self.assertIsInstance(empty_validation, ValidationResult)
|
||
|
|
self.assertIsInstance(empty_validation.quality_score, float)
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == '__main__':
|
||
|
|
# Run the tests
|
||
|
|
unittest.main(verbosity=2)
|