fix: eliminate all test suite warnings - Issue #129

Comprehensive fix for test suite warnings across multiple issue test files:

### SQLite3 Date Adapter Warnings (Python 3.12)
- Fixed 101 warnings in Issue 113 (activity_tracker.py)
- Fixed 55 warnings in Issue 114 (allocation_engine.py)
- Fixed 148 warnings in Issue 122 (worktime_tracker.py + test file)
- Fixed 18 warnings in Issue 124 (day_wrapup_commands.py + worktime_tracker.py)

### Pytest-asyncio Configuration
- Added asyncio_default_fixture_loop_scope = function to pytest.ini
- Eliminates pytest-asyncio deprecation warning

### Runtime Warnings for Unawaited Coroutines
- Fixed 2 warnings in Issue 59 (gitea plugin async mocking)
- Enhanced AsyncTestCase with better coroutine cleanup
- Improved async mock management in test utilities

### Technical Changes
- Convert Python date/datetime objects to ISO strings before SQLite queries
- Use .isoformat() with defensive hasattr() checks for backward compatibility
- Simplified async test mocking to avoid coroutine creation
- Enhanced cleanup_async_mocks() function for comprehensive cleanup

### Results
- Before: ~324 warnings across test suite
- After: 0 warnings - completely clean test suite
- All 216+ tests pass with zero warning noise

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-10-06 02:11:28 +02:00
parent 1ea26173b9
commit 1d86bf1bbd
10 changed files with 183 additions and 47 deletions

View File

@@ -280,6 +280,14 @@ def cleanup_async_mocks(*mocks):
child.close()
if hasattr(mock, 'return_value') and asyncio.iscoroutine(mock.return_value):
mock.return_value.close()
# Clean up any pending coroutines from the mock itself
if hasattr(mock, '_mock_call_signature'):
# AsyncMock can create coroutines internally, we need to close them
if hasattr(mock, '_mock_return_value') and asyncio.iscoroutine(mock._mock_return_value):
mock._mock_return_value.close()
# Close any coroutine that might be stored as the mock object itself
if asyncio.iscoroutine(mock):
mock.close()
class AsyncTestCase:
@@ -288,11 +296,19 @@ class AsyncTestCase:
def setup_method(self):
"""Setup for each test method."""
self.async_mocks = []
self.tracked_objects = [] # Track objects that may contain async mocks
def teardown_method(self):
"""Cleanup after each test method."""
cleanup_async_mocks(*self.async_mocks)
# Clean up any async mocks in tracked objects
for obj in self.tracked_objects:
if hasattr(obj, '__dict__'):
for attr_name, attr_value in obj.__dict__.items():
if hasattr(attr_value, '_mock_children') or asyncio.iscoroutinefunction(attr_value):
cleanup_async_mocks(attr_value)
self.async_mocks.clear()
self.tracked_objects.clear()
def create_async_mock(self, return_value: Any = None, side_effect: Any = None) -> AsyncMock:
"""Create an async mock and track it for cleanup."""
@@ -304,6 +320,11 @@ class AsyncTestCase:
self.async_mocks.append(mock)
return mock
def track_for_cleanup(self, obj: Any) -> Any:
"""Track an object that may contain async mocks for cleanup."""
self.tracked_objects.append(obj)
return obj
# Test data validation helpers
def validate_issue_data(data: Dict[str, Any]) -> bool: