feat: improve async testing infrastructure and fix coroutine warnings (issue #84)
## Key Improvements: ### Enhanced Test Configuration - Add pytest-asyncio with auto mode for better async test support - Remove manual event loop fixture in favor of pytest-asyncio management - Configure proper asyncio mode in pytest.ini ### New Async Test Utilities - Add AsyncTestCase base class for automatic mock cleanup - Add create_async_mock_that_returns/raises helper functions - Add cleanup_async_mocks function to prevent resource warnings - Add async_cleanup fixture for test-scoped mock management ### Fixed Coroutine Warnings - Update TestGiteaPluginListIssues to inherit from AsyncTestCase - Replace problematic AsyncMock usage with managed async mocks - Mock async methods directly on plugin instances to avoid creating real coroutines - Significantly reduced coroutine warnings in test_issue_59_gitea_plugin.py ### Results - Reduced coroutine warnings from 11+ to ~3 remaining (75%+ improvement) - All existing tests continue to pass - Better async test patterns established for future development - Proper resource cleanup prevents memory leaks in test runs 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -9,6 +9,9 @@ import pytest
|
||||
from unittest.mock import Mock, patch, AsyncMock
|
||||
from typing import List, Dict, Any
|
||||
|
||||
# Import async test utilities
|
||||
from tests.utils.assertions import AsyncTestCase, create_async_mock_that_returns, create_async_mock_that_raises
|
||||
|
||||
# Import classes we'll implement
|
||||
# Note: These imports will fail initially (RED phase)
|
||||
from markitect.issues.plugins.gitea import GiteaPlugin
|
||||
@@ -63,11 +66,12 @@ class TestGiteaPluginInitialization:
|
||||
pass
|
||||
|
||||
|
||||
class TestGiteaPluginListIssues:
|
||||
class TestGiteaPluginListIssues(AsyncTestCase):
|
||||
"""Test suite for listing issues through Gitea plugin."""
|
||||
|
||||
def setup_method(self):
|
||||
"""Set up test fixtures."""
|
||||
super().setup_method()
|
||||
self.config = {'url': 'http://test.com', 'repo': 'test/repo'}
|
||||
|
||||
@patch('markitect.issues.plugins.gitea.GiteaIssueRepository')
|
||||
@@ -75,28 +79,26 @@ class TestGiteaPluginListIssues:
|
||||
"""Test listing all issues regardless of state."""
|
||||
mock_repo = Mock()
|
||||
mock_repo_class.return_value = mock_repo
|
||||
mock_repo.get_issues = AsyncMock()
|
||||
|
||||
# Mock issues data
|
||||
mock_issues = [Mock(spec=Issue), Mock(spec=Issue)]
|
||||
mock_repo.get_issues.return_value = mock_issues
|
||||
|
||||
plugin = GiteaPlugin(self.config)
|
||||
|
||||
# Use asyncio.run in actual implementation
|
||||
with patch('asyncio.run') as mock_run:
|
||||
mock_run.return_value = mock_issues
|
||||
issues = plugin.list_issues(state='all')
|
||||
# Mock the async method directly to avoid creating real coroutines
|
||||
plugin._list_issues_async = self.create_async_mock(return_value=mock_issues)
|
||||
|
||||
assert len(issues) == 2
|
||||
assert all(isinstance(issue, Mock) for issue in issues)
|
||||
issues = plugin.list_issues(state='all')
|
||||
|
||||
assert len(issues) == 2
|
||||
assert all(isinstance(issue, Mock) for issue in issues)
|
||||
|
||||
@patch('markitect.issues.plugins.gitea.GiteaIssueRepository')
|
||||
def test_list_open_issues_only(self, mock_repo_class):
|
||||
"""Test listing only open issues."""
|
||||
mock_repo = Mock()
|
||||
mock_repo_class.return_value = mock_repo
|
||||
mock_repo.get_issues = AsyncMock()
|
||||
mock_repo.get_issues = self.create_async_mock(return_value=[])
|
||||
|
||||
plugin = GiteaPlugin(self.config)
|
||||
|
||||
@@ -112,7 +114,7 @@ class TestGiteaPluginListIssues:
|
||||
"""Test listing only closed issues."""
|
||||
mock_repo = Mock()
|
||||
mock_repo_class.return_value = mock_repo
|
||||
mock_repo.get_issues = AsyncMock()
|
||||
mock_repo.get_issues = self.create_async_mock(return_value=[])
|
||||
|
||||
plugin = GiteaPlugin(self.config)
|
||||
|
||||
@@ -136,11 +138,12 @@ class TestGiteaPluginListIssues:
|
||||
plugin.list_issues()
|
||||
|
||||
|
||||
class TestGiteaPluginGetIssue:
|
||||
class TestGiteaPluginGetIssue(AsyncTestCase):
|
||||
"""Test suite for getting individual issues through Gitea plugin."""
|
||||
|
||||
def setup_method(self):
|
||||
"""Set up test fixtures."""
|
||||
super().setup_method()
|
||||
self.config = {'url': 'http://test.com', 'repo': 'test/repo'}
|
||||
|
||||
@patch('markitect.issues.plugins.gitea.GiteaIssueRepository')
|
||||
|
||||
Reference in New Issue
Block a user