resumate / tests /test_github.py
gperdrizet's picture
Updated tests
d0f660b verified
raw
history blame
24.2 kB
"""
Unit tests for the github module.
"""
import unittest
from unittest.mock import patch, MagicMock
import requests
from functions import github
# pylint: disable=protected-access
class TestExtractGitHubUsername(unittest.TestCase):
"""Test cases for the _extract_github_username function."""
def test_valid_github_urls(self):
"""Test extraction from valid GitHub URLs."""
test_cases = [
("https://github.com/octocat", "octocat"),
("https://github.com/octocat/", "octocat"),
("http://github.com/test-user", "test-user"),
("github.com/user_name", "user_name"),
("https://github.com/user123", "user123"),
("https://github.com/octocat/Hello-World", "octocat"),
]
for url, expected in test_cases:
with self.subTest(url=url):
result = github._extract_github_username(url)
self.assertEqual(result, expected)
def test_invalid_github_urls(self):
"""Test handling of invalid GitHub URLs."""
invalid_urls = [
"",
"https://gitlab.com/user",
"https://github.com/",
"[email protected]",
"https://github.com/user-with-very-long-name-that-exceeds-github-limit",
None
]
for url in invalid_urls:
with self.subTest(url=url):
result = github._extract_github_username(url)
self.assertIsNone(result)
def test_username_validation(self):
"""Test username format validation."""
# Valid usernames
valid_usernames = ["user", "user-name", "user_name", "user123", "a" * 39]
for username in valid_usernames:
with self.subTest(username=username):
result = github._extract_github_username(f"github.com/{username}")
self.assertEqual(result, username)
# Invalid usernames
invalid_usernames = ["", "a" * 40, "user@name", "user.name"]
for username in invalid_usernames:
with self.subTest(username=username):
result = github._extract_github_username(f"github.com/{username}")
self.assertIsNone(result)
class TestGetGitHubUserInfo(unittest.TestCase):
"""Test cases for the _get_github_user_info function."""
@patch('requests.get')
def test_successful_user_info(self, mock_get):
"""Test successful user info retrieval."""
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = {
"login": "octocat",
"public_repos": 10,
"name": "The Octocat"
}
mock_get.return_value = mock_response
result = github._get_github_user_info("octocat")
self.assertEqual(result["status"], "success")
self.assertIn("data", result)
self.assertEqual(result["data"]["login"], "octocat")
@patch('requests.get')
def test_user_not_found(self, mock_get):
"""Test handling of non-existent user."""
mock_response = MagicMock()
mock_response.status_code = 404
mock_get.return_value = mock_response
result = github._get_github_user_info("nonexistentuser")
self.assertEqual(result["status"], "error")
self.assertIn("not found", result["message"])
@patch('requests.get')
def test_rate_limit_exceeded(self, mock_get):
"""Test handling of rate limit exceeded."""
mock_response = MagicMock()
mock_response.status_code = 403
mock_get.return_value = mock_response
result = github._get_github_user_info("octocat")
self.assertEqual(result["status"], "error")
self.assertIn("rate limit", result["message"])
@patch('requests.get')
def test_network_error(self, mock_get):
"""Test handling of network errors."""
mock_get.side_effect = requests.RequestException("Connection error")
result = github._get_github_user_info("octocat")
self.assertEqual(result["status"], "error")
self.assertIn("Network error", result["message"])
class TestGetUserRepositories(unittest.TestCase):
"""Test cases for the _get_user_repositories function."""
@patch('requests.get')
def test_successful_repository_retrieval(self, mock_get):
"""Test successful repository retrieval."""
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = [
{
"name": "Hello-World",
"description": "My first repository",
"language": "Python",
"stargazers_count": 5,
"forks_count": 2
}
]
mock_get.return_value = mock_response
result = github._get_user_repositories("octocat")
self.assertEqual(result["status"], "success")
self.assertIn("data", result)
self.assertEqual(len(result["data"]), 1)
self.assertEqual(result["data"][0]["name"], "Hello-World")
@patch('requests.get')
def test_empty_repository_list(self, mock_get):
"""Test handling of empty repository list."""
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = []
mock_get.return_value = mock_response
result = github._get_user_repositories("octocat")
self.assertEqual(result["status"], "success")
self.assertEqual(len(result["data"]), 0)
@patch('requests.get')
def test_api_error(self, mock_get):
"""Test handling of API errors."""
mock_response = MagicMock()
mock_response.status_code = 500
mock_get.return_value = mock_response
result = github._get_user_repositories("octocat")
self.assertEqual(result["status"], "error")
self.assertIn("GitHub API error", result["message"])
class TestProcessRepositoryData(unittest.TestCase):
"""Test cases for the _process_repository_data function."""
def test_basic_processing(self):
"""Test basic repository data processing."""
raw_repos = [
{
"name": "test-repo",
"description": "Test repository",
"language": "Python",
"stargazers_count": 10,
"forks_count": 5,
"updated_at": "2024-01-01T00:00:00Z",
"html_url": "https://github.com/user/test-repo",
"topics": ["python", "test"],
"fork": False
}
]
result = github._process_repository_data(raw_repos)
self.assertEqual(len(result), 1)
processed_repo = result[0]
self.assertEqual(processed_repo["name"], "test-repo")
self.assertEqual(processed_repo["description"], "Test repository")
self.assertEqual(processed_repo["language"], "Python")
self.assertEqual(processed_repo["stars"], 10)
self.assertEqual(processed_repo["forks"], 5)
self.assertFalse(processed_repo["is_fork"])
def test_fork_filtering(self):
"""Test filtering of unmodified forks."""
raw_repos = [
{
"name": "original-repo",
"fork": False,
"stargazers_count": 5
},
{
"name": "unmodified-fork",
"fork": True,
"stargazers_count": 0
},
{
"name": "modified-fork",
"fork": True,
"stargazers_count": 3
}
]
result = github._process_repository_data(raw_repos)
# Should include original repo and modified fork, exclude unmodified fork
self.assertEqual(len(result), 2)
repo_names = [repo["name"] for repo in result]
self.assertIn("original-repo", repo_names)
self.assertIn("modified-fork", repo_names)
self.assertNotIn("unmodified-fork", repo_names)
def test_missing_fields(self):
"""Test handling of missing fields in repository data."""
raw_repos = [
{
"name": "minimal-repo"
# Missing most optional fields
}
]
result = github._process_repository_data(raw_repos)
self.assertEqual(len(result), 1)
processed_repo = result[0]
self.assertEqual(processed_repo["name"], "minimal-repo")
self.assertEqual(processed_repo["description"], "")
self.assertEqual(processed_repo["language"], "")
self.assertEqual(processed_repo["stars"], 0)
self.assertEqual(processed_repo["forks"], 0)
class TestGetGitHubRepositories(unittest.TestCase):
"""Test cases for the get_github_repositories function."""
def test_empty_url(self):
"""Test handling of empty or None URL."""
test_cases = [None, "", " "]
for url in test_cases:
with self.subTest(url=url):
result = github.get_github_repositories(url)
self.assertEqual(result["status"], "error")
self.assertIn("No GitHub URL provided", result["message"])
@patch('functions.github._get_user_repositories')
@patch('functions.github._get_github_user_info')
@patch('functions.github._extract_github_username')
def test_successful_retrieval(self, mock_extract, mock_user_info, mock_repos):
"""Test successful repository retrieval."""
mock_extract.return_value = "octocat"
mock_user_info.return_value = {
"status": "success",
"data": {"public_repos": 10}
}
mock_repos.return_value = {
"status": "success",
"data": [{"name": "Hello-World", "fork": False, "stargazers_count": 5}]
}
result = github.get_github_repositories("https://github.com/octocat")
self.assertEqual(result["status"], "success")
self.assertIn("repositories", result)
self.assertIn("metadata", result)
self.assertEqual(result["metadata"]["username"], "octocat")
def test_invalid_url_format(self):
"""Test handling of invalid URL format."""
result = github.get_github_repositories("https://gitlab.com/user")
self.assertEqual(result["status"], "error")
self.assertIn("Invalid GitHub URL format", result["message"])
class TestFormatRepositoriesForLLM(unittest.TestCase):
"""Test cases for the format_repositories_for_llm function."""
def test_successful_formatting(self):
"""Test successful formatting of repository data."""
github_result = {
"status": "success",
"repositories": [
{
"name": "test-repo",
"description": "A test repository",
"language": "Python",
"stars": 10,
"forks": 5,
"updated_at": "2024-01-01T00:00:00Z",
"html_url": "https://github.com/user/test-repo",
"topics": ["python", "test"]
}
],
"metadata": {
"username": "testuser",
"profile_url": "https://github.com/testuser"
}
}
result = github.format_repositories_for_llm(github_result)
self.assertIn("=== GITHUB REPOSITORIES ===", result)
self.assertIn("testuser", result)
self.assertIn("test-repo", result)
self.assertIn("A test repository", result)
self.assertIn("Python", result)
self.assertIn("=== END GITHUB REPOSITORIES ===", result)
def test_error_status(self):
"""Test formatting when there's an error status."""
github_result = {
"status": "error",
"message": "User not found"
}
result = github.format_repositories_for_llm(github_result)
self.assertIn("could not be retrieved", result)
self.assertIn("User not found", result)
def test_no_repositories(self):
"""Test formatting when no repositories are found."""
github_result = {
"status": "success",
"repositories": [],
"metadata": {"username": "emptyuser"}
}
result = github.format_repositories_for_llm(github_result)
self.assertIn("No public repositories found", result)
self.assertIn("emptyuser", result)
def test_many_repositories_limit(self):
"""Test that formatting limits to 20 repositories."""
repositories = []
for i in range(25):
repositories.append({
"name": f"repo-{i}",
"description": f"Repository {i}",
"language": "Python",
"stars": i,
"forks": 0,
"updated_at": "2024-01-01T00:00:00Z",
"html_url": f"https://github.com/user/repo-{i}",
"topics": []
})
github_result = {
"status": "success",
"repositories": repositories,
"metadata": {"username": "manyrepos"}
}
result = github.format_repositories_for_llm(github_result)
# Should mention "and 5 more repositories"
self.assertIn("and 5 more repositories", result)
# Should contain the first 20 repos
self.assertIn("repo-0", result)
self.assertIn("repo-19", result)
# Should not contain repos beyond 20
self.assertNotIn("repo-20", result)
class TestGetRepositoryDetails(unittest.TestCase):
"""Test cases for the get_repository_details function."""
def test_invalid_repository_url(self):
"""Test handling of invalid repository URLs."""
invalid_urls = [
"",
None,
"https://gitlab.com/user/repo",
"https://github.com/",
"https://github.com/user",
"not-a-url",
]
for url in invalid_urls:
with self.subTest(url=url):
result = github.get_repository_details(url)
self.assertEqual(result["status"], "error")
self.assertIn("message", result)
@patch('functions.github._get_repository_info')
@patch('functions.github._extract_repo_info')
def test_repository_not_found(self, mock_extract, mock_get_info):
"""Test handling of non-existent repository."""
mock_extract.return_value = ("user", "nonexistent-repo")
mock_get_info.return_value = {
"status": "error",
"message": "Repository 'user/nonexistent-repo' not found"
}
result = github.get_repository_details("https://github.com/user/nonexistent-repo")
self.assertEqual(result["status"], "error")
self.assertIn("not found", result["message"])
@patch('functions.github._get_repository_contributors')
@patch('functions.github._get_repository_releases')
@patch('functions.github._get_repository_contents')
@patch('functions.github._get_repository_readme')
@patch('functions.github._get_repository_languages')
@patch('functions.github._get_repository_info')
@patch('functions.github._extract_repo_info')
def test_successful_repository_details(self, mock_extract, mock_get_info,
mock_languages, mock_readme, mock_contents,
mock_releases, mock_contributors):
"""Test successful repository details retrieval."""
# Mock URL extraction
mock_extract.return_value = ("octocat", "Hello-World")
# Mock basic repository info
mock_get_info.return_value = {
"status": "success",
"data": {
"name": "Hello-World",
"full_name": "octocat/Hello-World",
"description": "This your first repo!",
"language": "C",
"stargazers_count": 80,
"forks_count": 9,
"watchers_count": 80,
"size": 108,
"created_at": "2011-01-26T19:01:12Z",
"updated_at": "2011-01-26T19:14:43Z",
"pushed_at": "2011-01-26T19:06:43Z",
"html_url": "https://github.com/octocat/Hello-World",
"clone_url": "https://github.com/octocat/Hello-World.git",
"ssh_url": "[email protected]:octocat/Hello-World.git",
"topics": ["example", "tutorial"],
"license": {"name": "MIT License", "spdx_id": "MIT"},
"fork": False,
"archived": False,
"private": False,
"default_branch": "master",
"open_issues_count": 0,
"has_issues": True,
"has_wiki": True,
"has_pages": False,
"has_projects": True,
"visibility": "public"
}
}
# Mock additional data
mock_languages.return_value = {
"status": "success",
"data": {"C": 78.1, "Makefile": 21.9}
}
mock_readme.return_value = {
"status": "success",
"data": "# Hello World\n\nThis is a test repository."
}
mock_contents.return_value = {
"status": "success",
"data": ["README.md", "hello.c", "Makefile"]
}
mock_releases.return_value = {
"status": "success",
"data": [
{
"tag_name": "v1.0.0",
"name": "First Release",
"published_at": "2011-01-26T19:14:43Z",
"prerelease": False,
"draft": False
}
]
}
mock_contributors.return_value = {
"status": "success",
"data": [
{
"login": "octocat",
"contributions": 32,
"html_url": "https://github.com/octocat",
"type": "User"
}
]
}
result = github.get_repository_details("https://github.com/octocat/Hello-World")
# Verify success
self.assertEqual(result["status"], "success")
self.assertIn("repository", result)
repo = result["repository"]
# Verify basic info
self.assertEqual(repo["name"], "Hello-World")
self.assertEqual(repo["full_name"], "octocat/Hello-World")
self.assertEqual(repo["description"], "This your first repo!")
self.assertEqual(repo["language"], "C")
self.assertEqual(repo["stars"], 80)
self.assertEqual(repo["forks"], 9)
# Verify additional data
self.assertEqual(repo["languages"], {"C": 78.1, "Makefile": 21.9})
self.assertIn("Hello World", repo["readme"])
self.assertEqual(repo["file_structure"], ["README.md", "hello.c", "Makefile"])
self.assertEqual(len(repo["releases"]), 1)
self.assertEqual(repo["releases"][0]["tag_name"], "v1.0.0")
self.assertEqual(len(repo["contributors"]), 1)
self.assertEqual(repo["contributors"][0]["login"], "octocat")
# Verify boolean flags
self.assertFalse(repo["is_fork"])
self.assertFalse(repo["is_archived"])
self.assertFalse(repo["is_private"])
self.assertTrue(repo["has_issues"])
def test_extract_repo_info_valid_urls(self):
"""Test _extract_repo_info with valid repository URLs."""
test_cases = [
("https://github.com/octocat/Hello-World", ("octocat", "Hello-World")),
("https://github.com/user/repo.git", ("user", "repo")),
("https://github.com/org/project/", ("org", "project")),
("github.com/test/example", ("test", "example")),
("https://github.com/user/repo/issues", ("user", "repo")),
]
for url, expected in test_cases:
with self.subTest(url=url):
result = github._extract_repo_info(url)
self.assertEqual(result, expected)
def test_extract_repo_info_invalid_urls(self):
"""Test _extract_repo_info with invalid repository URLs."""
invalid_urls = [
"",
"https://gitlab.com/user/repo",
"https://github.com/user",
"https://github.com/",
"not-a-url",
]
for url in invalid_urls:
with self.subTest(url=url):
result = github._extract_repo_info(url)
self.assertEqual(result, (None, None))
@patch('requests.get')
def test_get_repository_info_success(self, mock_get):
"""Test _get_repository_info with successful response."""
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = {
"name": "test-repo",
"full_name": "user/test-repo"
}
mock_get.return_value = mock_response
result = github._get_repository_info("user", "test-repo")
self.assertEqual(result["status"], "success")
self.assertIn("data", result)
self.assertEqual(result["data"]["name"], "test-repo")
@patch('requests.get')
def test_get_repository_info_not_found(self, mock_get):
"""Test _get_repository_info with 404 response."""
mock_response = MagicMock()
mock_response.status_code = 404
mock_get.return_value = mock_response
result = github._get_repository_info("user", "nonexistent")
self.assertEqual(result["status"], "error")
self.assertIn("not found", result["message"])
@patch('requests.get')
def test_get_repository_languages_success(self, mock_get):
"""Test _get_repository_languages with successful response."""
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = {
"Python": 50000,
"JavaScript": 25000,
"CSS": 25000
}
mock_get.return_value = mock_response
result = github._get_repository_languages("user", "repo")
self.assertEqual(result["status"], "success")
expected_percentages = {"Python": 50.0, "JavaScript": 25.0, "CSS": 25.0}
self.assertEqual(result["data"], expected_percentages)
@patch('requests.get')
def test_get_repository_readme_success(self, mock_get):
"""Test _get_repository_readme with successful response."""
# Mock the README metadata response
readme_response = MagicMock()
readme_response.status_code = 200
readme_response.json.return_value = {
"download_url": "https://raw.githubusercontent.com/user/repo/main/README.md"
}
# Mock the README content response
content_response = MagicMock()
content_response.status_code = 200
content_response.text = "# Test Repository\n\nThis is a test."
mock_get.side_effect = [readme_response, content_response]
result = github._get_repository_readme("user", "repo")
self.assertEqual(result["status"], "success")
self.assertIn("Test Repository", result["data"])
@patch('requests.get')
def test_get_repository_contents_success(self, mock_get):
"""Test _get_repository_contents with successful response."""
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = [
{"name": "src", "type": "dir"},
{"name": "README.md", "type": "file"},
{"name": "setup.py", "type": "file"},
{"name": "tests", "type": "dir"}
]
mock_get.return_value = mock_response
result = github._get_repository_contents("user", "repo")
self.assertEqual(result["status"], "success")
expected_structure = ["src/", "tests/", "README.md", "setup.py"]
self.assertEqual(result["data"], expected_structure)
if __name__ == '__main__':
unittest.main()