import pytest from datetime import datetime from unittest.mock import patch, MagicMock class TestCommitPatternAnalyzer: """Test CommitPatternAnalyzer.""" @pytest.fixture def mock_commit(self): return MagicMock( sha="abc123", message="Test commit", author_name="John Doe", author_email="john@test.com", committed_datetime=datetime(2024, 1, 15, 10, 30, 0), author_datetime=datetime(2024, 1, 15, 10, 30, 0), additions=50, deletions=10, files_changed=["src/main.py"], parents=[], is_merge=False, ) def test_analyze_empty_repo(self): """Test analyzing empty repository.""" with patch('src.analyzers.git_repository.GitRepository.get_commits', return_value=[]): from src.analyzers import CommitPatternAnalyzer analyzer = CommitPatternAnalyzer(MagicMock(), days=30) result = analyzer.analyze() assert result.total_commits == 0 assert result.unique_authors == 0 def test_analyze_with_commits(self, mock_commit): """Test analyzing repository with commits.""" with patch('src.analyzers.git_repository.GitRepository.get_commits', return_value=[mock_commit]): from src.analyzers import CommitPatternAnalyzer analyzer = CommitPatternAnalyzer(MagicMock(), days=30) result = analyzer.analyze() assert result.total_commits == 1 assert result.unique_authors == 1 class TestCodeChurnAnalyzer: """Test CodeChurnAnalyzer.""" @pytest.fixture def mock_commit(self): return MagicMock( sha="abc123", message="Large commit", author_name="Jane", author_email="jane@test.com", committed_datetime=datetime.now(), author_datetime=datetime.now(), additions=1000, deletions=100, files_changed=["src/main.py"], lines_changed_count=1100, parents=[], is_merge=False, ) def test_analyze_empty_repo(self): """Test analyzing empty repository.""" with patch('src.analyzers.git_repository.GitRepository.get_commits', return_value=[]): from src.analyzers import CodeChurnAnalyzer analyzer = CodeChurnAnalyzer(MagicMock(), days=30) result = analyzer.analyze() assert result.total_lines_added == 0 assert result.total_lines_deleted == 0 def test_churn_threshold(self, mock_commit): """Test churn threshold detection.""" with patch('src.analyzers.git_repository.GitRepository.get_commits', return_value=[mock_commit]): from src.analyzers import CodeChurnAnalyzer analyzer = CodeChurnAnalyzer(MagicMock(), days=30, churn_threshold=500) result = analyzer.analyze() assert len(result.high_churn_files) >= 0 class TestVelocityAnalyzer: """Test VelocityAnalyzer.""" @pytest.fixture def mock_commits(self): commits = [] for i in range(7): commit = MagicMock( sha=f"sha{i}", message=f"Commit {i}", author_name="John", author_email="john@test.com", committed_datetime=datetime(2024, 1, i + 1, 10, 0, 0), author_datetime=datetime(2024, 1, i + 1, 10, 0, 0), additions=10, deletions=5, files_changed=["src/file.py"], lines_changed_count=15, parents=[], is_merge=False, ) commits.append(commit) return commits def test_analyze_empty_repo(self): """Test analyzing empty repository.""" with patch('src.analyzers.git_repository.GitRepository.get_commits', return_value=[]): from src.analyzers import VelocityAnalyzer analyzer = VelocityAnalyzer(MagicMock(), days=30) result = analyzer.analyze() assert result.total_commits == 0 assert result.commits_per_day == 0.0 def test_velocity_calculation(self, mock_commits): """Test velocity calculation.""" with patch('src.analyzers.git_repository.GitRepository.get_commits', return_value=mock_commits): from src.analyzers import VelocityAnalyzer analyzer = VelocityAnalyzer(MagicMock(), days=7) result = analyzer.analyze() assert result.total_commits == 7 assert result.commits_per_day == 1.0 class TestRiskyCommitDetector: """Test RiskyCommitDetector.""" @pytest.fixture def mock_large_commit(self): return MagicMock( sha="abc123", message="Huge commit", author_name="John", author_email="john@test.com", committed_datetime=datetime.now(), author_datetime=datetime.now(), additions=1000, deletions=500, files_changed=["src/main.py"], lines_changed_count=1500, parents=[], is_merge=False, ) @pytest.fixture def mock_merge_commit(self): return MagicMock( sha="def456", message="Merge branch", author_name="Jane", author_email="jane@test.com", committed_datetime=datetime.now(), author_datetime=datetime.now(), additions=10, deletions=5, files_changed=["src/main.py"], lines_changed_count=15, parents=["parent1", "parent2"], is_merge=True, ) def test_detect_large_commits(self, mock_large_commit): """Test detecting large commits.""" with patch('src.analyzers.git_repository.GitRepository.get_commits', return_value=[mock_large_commit]): from src.analyzers import RiskyCommitDetector detector = RiskyCommitDetector(MagicMock(), days=30, large_commit_threshold=500) result = detector.analyze() assert len(result.large_commits) == 1 def test_detect_merge_commits(self, mock_merge_commit): """Test detecting merge commits.""" with patch('src.analyzers.git_repository.GitRepository.get_commits', return_value=[mock_merge_commit]): from src.analyzers import RiskyCommitDetector detector = RiskyCommitDetector(MagicMock(), days=30) result = detector.analyze() assert len(result.merge_commits) == 1