feat: implement tddai Python library for TDD workspace management
- Create comprehensive tddai package with workspace, issue fetcher, and test generator modules - Add Python CLI interface (tddai_cli.py) to replace complex Makefile shell logic - Update Makefile targets to use Python CLI for better maintainability - Implement proper behavior-based tests instead of file existence checks - Add workspace lifecycle management (create, active, finish, cleanup) - Add issue fetching from Gitea API with error handling - Add comprehensive test coverage with 19 passing tests - Support environment variable configuration for different deployments This addresses issue #11: Setup TDD workspace infrastructure All tests pass and the system achieves green state before commit. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
194
tests/test_issue_11_workflow_integration.py
Normal file
194
tests/test_issue_11_workflow_integration.py
Normal file
@@ -0,0 +1,194 @@
|
||||
"""
|
||||
Test TDD workflow integration for workspace infrastructure.
|
||||
|
||||
This test validates issue #11: Setup TDD workspace infrastructure
|
||||
- Tests complete workflow from start to finish
|
||||
- Validates integration between workspace and main codebase
|
||||
- Tests cleanup and finalization processes
|
||||
"""
|
||||
|
||||
import pytest
|
||||
import subprocess
|
||||
import tempfile
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
|
||||
from tddai import WorkspaceManager, IssueFetcher
|
||||
from tddai.config import TddaiConfig
|
||||
|
||||
|
||||
class TestWorkflowIntegration:
|
||||
"""Test suite for complete TDD workflow integration."""
|
||||
|
||||
@pytest.fixture
|
||||
def temp_workspace(self):
|
||||
"""Create a temporary workspace for testing."""
|
||||
temp_dir = Path(tempfile.mkdtemp())
|
||||
config = TddaiConfig(workspace_dir=temp_dir / ".markitect_workspace")
|
||||
yield config
|
||||
shutil.rmtree(temp_dir)
|
||||
|
||||
def test_make_workspace_status_command(self):
|
||||
"""Test that make workspace-status command works correctly."""
|
||||
result = subprocess.run(['make', 'workspace-status'],
|
||||
capture_output=True, text=True)
|
||||
|
||||
assert result.returncode == 0, "workspace-status command should succeed"
|
||||
# Should show clean workspace when no active workspace
|
||||
assert ("No active issue workspace" in result.stdout or
|
||||
"Workspace directory exists but no current issue file" in result.stdout)
|
||||
|
||||
def test_make_add_test_command_without_workspace(self):
|
||||
"""Test that make add-test provides proper error when no workspace."""
|
||||
result = subprocess.run(['make', 'add-test'],
|
||||
capture_output=True, text=True)
|
||||
|
||||
assert result.returncode != 0, "add-test command should fail when no workspace"
|
||||
assert "No active issue workspace" in result.stdout
|
||||
|
||||
def test_cli_integration_basic(self):
|
||||
"""Test that CLI script can be imported and basic functions exist."""
|
||||
import tddai_cli
|
||||
|
||||
# Test that main functions exist
|
||||
assert hasattr(tddai_cli, 'workspace_status')
|
||||
assert hasattr(tddai_cli, 'start_issue')
|
||||
assert hasattr(tddai_cli, 'finish_issue')
|
||||
assert hasattr(tddai_cli, 'main')
|
||||
|
||||
def test_workspace_to_main_integration(self, temp_workspace):
|
||||
"""Test moving tests from workspace to main tests directory."""
|
||||
manager = WorkspaceManager(temp_workspace)
|
||||
|
||||
mock_issue_data = {
|
||||
'number': 11,
|
||||
'title': 'Test Issue',
|
||||
'body': 'Test Description',
|
||||
'state': 'open',
|
||||
'created_at': '2025-01-01T00:00:00Z',
|
||||
'html_url': 'http://example.com/issues/11',
|
||||
'assignee': None,
|
||||
'labels': []
|
||||
}
|
||||
|
||||
# Create workspace
|
||||
workspace = manager.create_workspace(mock_issue_data)
|
||||
|
||||
# Add a test file to workspace
|
||||
test_file = workspace.tests_dir / "test_issue_11_feature.py"
|
||||
test_content = '''"""Test for issue #11."""
|
||||
import pytest
|
||||
|
||||
def test_feature():
|
||||
"""Test the feature implementation."""
|
||||
assert True # Replace with actual test
|
||||
'''
|
||||
test_file.write_text(test_content)
|
||||
|
||||
# Finish workspace (should move tests)
|
||||
finished_workspace = manager.finish_workspace()
|
||||
|
||||
# Verify test was moved to main tests directory
|
||||
main_test_file = temp_workspace.tests_dir / "test_issue_11_feature.py"
|
||||
assert main_test_file.exists()
|
||||
assert main_test_file.read_text() == test_content
|
||||
|
||||
# Verify workspace is cleaned up
|
||||
assert not temp_workspace.workspace_dir.exists()
|
||||
|
||||
def test_workspace_cleanup_process(self, temp_workspace):
|
||||
"""Test that workspace cleanup removes temporary files."""
|
||||
manager = WorkspaceManager(temp_workspace)
|
||||
|
||||
mock_issue_data = {
|
||||
'number': 11,
|
||||
'title': 'Test Issue',
|
||||
'body': 'Test Description',
|
||||
'state': 'open'
|
||||
}
|
||||
|
||||
# Create workspace
|
||||
workspace = manager.create_workspace(mock_issue_data)
|
||||
|
||||
# Verify workspace exists
|
||||
assert workspace.workspace_dir.exists()
|
||||
assert workspace.issue_dir.exists()
|
||||
|
||||
# Clean up
|
||||
manager.cleanup_workspace()
|
||||
|
||||
# Verify cleanup
|
||||
assert not workspace.workspace_dir.exists()
|
||||
|
||||
def test_gitignore_excludes_workspace(self):
|
||||
"""Test that workspace files are properly excluded from git."""
|
||||
gitignore_path = Path(".gitignore")
|
||||
assert gitignore_path.exists(), "Gitignore file should exist"
|
||||
|
||||
with open(gitignore_path, 'r') as f:
|
||||
gitignore_content = f.read()
|
||||
|
||||
assert ".markitect_workspace/" in gitignore_content, \
|
||||
"Workspace should be excluded from git"
|
||||
|
||||
@patch('tddai.issue_fetcher.subprocess.run')
|
||||
def test_issue_fetcher_integration(self, mock_run, temp_workspace):
|
||||
"""Test that IssueFetcher properly integrates with API."""
|
||||
# Mock successful curl response
|
||||
mock_run.return_value.returncode = 0
|
||||
mock_run.return_value.stdout = """{
|
||||
"number": 11,
|
||||
"title": "Setup TDD workspace infrastructure",
|
||||
"body": "Create workspace management system",
|
||||
"state": "open",
|
||||
"created_at": "2025-01-01T00:00:00Z",
|
||||
"updated_at": "2025-01-01T00:00:00Z",
|
||||
"html_url": "http://example.com/issues/11",
|
||||
"assignee": null,
|
||||
"labels": []
|
||||
}"""
|
||||
|
||||
fetcher = IssueFetcher(temp_workspace)
|
||||
issue = fetcher.fetch_issue(11)
|
||||
|
||||
assert issue.number == 11
|
||||
assert issue.title == "Setup TDD workspace infrastructure"
|
||||
assert issue.state == "open"
|
||||
|
||||
def test_complete_workflow_cycle(self, temp_workspace):
|
||||
"""Test complete workflow from start to finish."""
|
||||
manager = WorkspaceManager(temp_workspace)
|
||||
|
||||
mock_issue_data = {
|
||||
'number': 11,
|
||||
'title': 'Setup TDD workspace infrastructure',
|
||||
'body': 'Create workspace management system for TDD workflow',
|
||||
'state': 'open',
|
||||
'created_at': '2025-01-01T00:00:00Z',
|
||||
'html_url': 'http://example.com/issues/11',
|
||||
'assignee': None,
|
||||
'labels': []
|
||||
}
|
||||
|
||||
# 1. Start with clean workspace
|
||||
assert manager.get_status().name == "CLEAN"
|
||||
|
||||
# 2. Create workspace
|
||||
workspace = manager.create_workspace(mock_issue_data)
|
||||
assert manager.get_status().name == "ACTIVE"
|
||||
assert workspace.issue_number == 11
|
||||
|
||||
# 3. Add test files
|
||||
test_file = workspace.tests_dir / "test_issue_11_complete.py"
|
||||
test_file.write_text("# Complete test content")
|
||||
|
||||
# 4. Finish workspace
|
||||
finished = manager.finish_workspace()
|
||||
assert finished.issue_number == 11
|
||||
assert manager.get_status().name == "CLEAN"
|
||||
|
||||
# 5. Verify test moved to main
|
||||
main_test = temp_workspace.tests_dir / "test_issue_11_complete.py"
|
||||
assert main_test.exists()
|
||||
assert main_test.read_text() == "# Complete test content"
|
||||
Reference in New Issue
Block a user