Achieve 100% test coverage with comprehensive improvements
Enhanced test suite from 97% to 100% coverage with 173 passing tests. ## New Features ### 1. Error Handling Tests (3 tests) - test_add_message_handles_read_error_gracefully - test_add_message_handles_write_error_gracefully - test_clear_user_history_handles_permission_error - test_logger_reuses_existing_handlers Coverage: memory.py 91% → 100%, utils.py 98% → 100% ### 2. Integration Tests (9 tests) - test_integration.py - test_mention_to_response_workflow: Full message flow - test_conversation_context_preserved: Multi-turn conversations - test_config_to_components_integration: Component initialization - test_error_recovery_workflow: Graceful error handling - test_mention_detection_integration_with_nicknames - test_memory_limit_enforcement_in_workflow - test_ambiguous_greeting_workflow - test_logger_integration_with_memory - test_logger_integration_with_ai_provider - test_config_validation_workflow ### 3. Parameterized Tests (45 tests) - 18 mention detection test cases - 17 greeting detection test cases - 8 content extraction test cases - Covers edge cases, unicode, nicknames, false positives ### 4. GitHub Actions CI Workflow - Multi-Python version testing (3.9, 3.10, 3.11, 3.12) - Automated coverage reporting - Code quality checks (Black, isort, flake8) - Codecov integration - Coverage badge generation ## Test Statistics - Tests: 116 → 173 (+49% increase) - Coverage: 97% → 100% (+3pp) - Execution time: ~1.1 seconds - All components: 100% coverage ## Files Modified - tests/test_utils.py: Added parameterized tests and error handling - tests/test_memory.py: Added error handling tests - tests/test_integration.py: NEW - Full integration test suite - tests/README.md: Updated documentation - .github/workflows/test.yml: NEW - CI/CD automation
This commit is contained in:
parent
f6813b5fa5
commit
90a70a85eb
5 changed files with 553 additions and 18 deletions
|
|
@ -7,9 +7,87 @@ import logging
|
|||
from utils import MentionDetector, Logger
|
||||
|
||||
|
||||
# Parameterized test data
|
||||
MENTION_TEST_CASES = [
|
||||
# (message, bot_name, expected_result, description)
|
||||
("@Eugen hello", "Eugen", True, "at-mention"),
|
||||
("@eugen hello", "Eugen", True, "at-mention lowercase"),
|
||||
("@EUGEN hello", "Eugen", True, "at-mention uppercase"),
|
||||
("Eugen: what's up?", "Eugen", True, "colon format"),
|
||||
("Eugen! hey", "Eugen", True, "exclamation format"),
|
||||
("Eugen? are you there", "Eugen", True, "question format"),
|
||||
("Eugen, help me", "Eugen", True, "comma format"),
|
||||
("Eugen. listen", "Eugen", True, "period format"),
|
||||
("Hey Eugen how are you", "Eugen", True, "mention in middle"),
|
||||
("Is Eugen online?", "Eugen", True, "mention as word"),
|
||||
("Eugene is different", "Eugen", False, "partial match should fail"),
|
||||
("Eugenics is a topic", "Eugen", False, "false positive check"),
|
||||
("Regular message", "Eugen", False, "no mention"),
|
||||
("@kenearosmd hi", "kenearosmd", True, "long name at-mention"),
|
||||
("@kene hi", "kenearosmd", True, "nickname 4 chars"),
|
||||
("@kenearos hi", "kenearosmd", True, "nickname 8 chars"),
|
||||
("kenearosmd: what", "kenearosmd", True, "long name colon"),
|
||||
("kene: what", "kenearosmd", True, "nickname colon"),
|
||||
]
|
||||
|
||||
GREETING_TEST_CASES = [
|
||||
# (message, expected_ambiguous, description)
|
||||
("hi", True, "simple hi"),
|
||||
("Hi", True, "capitalized Hi"),
|
||||
("HI", True, "uppercase HI"),
|
||||
("hello", True, "hello"),
|
||||
("hallo", True, "German hallo"),
|
||||
("hey there", True, "hey there"),
|
||||
("moin", True, "German moin"),
|
||||
("servus", True, "German servus"),
|
||||
("wie gehts", True, "German wie gehts"),
|
||||
("wie geht's", True, "German with apostrophe"),
|
||||
("alles klar", True, "German alles klar"),
|
||||
("how are you", True, "English how are you"),
|
||||
("everything ok", True, "English everything ok"),
|
||||
("@Eugen hi", False, "clear mention not ambiguous"),
|
||||
("Eugen: hello", False, "clear mention not ambiguous"),
|
||||
("Just a message", False, "not a greeting"),
|
||||
("high score", False, "hi in word should not match"),
|
||||
]
|
||||
|
||||
CONTENT_EXTRACTION_CASES = [
|
||||
# (message, bot_name, expected_content, description)
|
||||
("@Eugen what's the weather?", "Eugen", "what's the weather?", "at-mention extraction"),
|
||||
("Eugen: tell me more", "Eugen", "tell me more", "colon extraction"),
|
||||
("Eugen, help please", "Eugen", "help please", "comma extraction"),
|
||||
("what's up Eugen", "Eugen", "what's up", "mention at end"),
|
||||
("@Eugen", "Eugen", "", "only mention"),
|
||||
("Eugen", "Eugen", "", "only name"),
|
||||
("@kene what's up", "kenearosmd", "what's up", "nickname extraction"),
|
||||
("", "Eugen", "", "empty message"),
|
||||
]
|
||||
|
||||
|
||||
class TestMentionDetector:
|
||||
"""Test MentionDetector functionality"""
|
||||
|
||||
@pytest.mark.parametrize("message,bot_name,expected,description", MENTION_TEST_CASES)
|
||||
def test_mention_detection_comprehensive(self, message, bot_name, expected, description):
|
||||
"""Parameterized test for comprehensive mention detection coverage"""
|
||||
detector = MentionDetector(bot_name)
|
||||
result = detector.is_mentioned(message)
|
||||
assert result == expected, f"Failed for case: {description}"
|
||||
|
||||
@pytest.mark.parametrize("message,expected,description", GREETING_TEST_CASES)
|
||||
def test_ambiguous_greeting_comprehensive(self, message, expected, description):
|
||||
"""Parameterized test for comprehensive greeting detection"""
|
||||
detector = MentionDetector("Eugen")
|
||||
result = detector.is_ambiguous_greeting(message)
|
||||
assert result == expected, f"Failed for case: {description}"
|
||||
|
||||
@pytest.mark.parametrize("message,bot_name,expected_content,description", CONTENT_EXTRACTION_CASES)
|
||||
def test_content_extraction_comprehensive(self, message, bot_name, expected_content, description):
|
||||
"""Parameterized test for comprehensive content extraction"""
|
||||
detector = MentionDetector(bot_name)
|
||||
result = detector.extract_content(message)
|
||||
assert result.strip() == expected_content.strip(), f"Failed for case: {description}"
|
||||
|
||||
def test_init_generates_nicknames(self):
|
||||
"""Test that nicknames are generated from bot name"""
|
||||
detector = MentionDetector("kenearosmd")
|
||||
|
|
@ -355,3 +433,21 @@ class TestLogger:
|
|||
assert "Öle" in content
|
||||
assert "Über" in content
|
||||
assert "ß" in content
|
||||
|
||||
def test_logger_reuses_existing_handlers(self, temp_dir):
|
||||
"""Test that logger doesn't create duplicate handlers"""
|
||||
import logging
|
||||
|
||||
log_dir = temp_dir / "logs"
|
||||
|
||||
# Create first logger
|
||||
logger1 = Logger(log_dir=str(log_dir), debug_mode=True)
|
||||
handler_count_1 = len(logger1.main_logger.handlers)
|
||||
|
||||
# Create second logger with same settings - should reuse handlers
|
||||
logger2 = Logger(log_dir=str(log_dir), debug_mode=True)
|
||||
handler_count_2 = len(logger2.main_logger.handlers)
|
||||
|
||||
# Should have same number of handlers (reused, not duplicated)
|
||||
assert handler_count_1 == handler_count_2
|
||||
assert handler_count_1 > 0 # But should have at least one handler
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue