diff --git a/.gitignore b/.gitignore index 890862e..823910c 100644 --- a/.gitignore +++ b/.gitignore @@ -162,6 +162,7 @@ cython_debug/ test.py +etest.py sonar-project.properties wget-log .scannerwork diff --git a/metricheq/connectors/sonar.py b/metricheq/connectors/sonar.py index 78ddb65..47bfffa 100644 --- a/metricheq/connectors/sonar.py +++ b/metricheq/connectors/sonar.py @@ -8,6 +8,8 @@ ) from pydantic import BaseModel +from metricheq.exceptions.exceptions import UnsupportedConfigurationError + class SonarBaseConfig(BaseModel): host_url: str @@ -25,18 +27,18 @@ class SonarUserPasswordConfig(SonarBaseConfig): class SonarClient(Client): def __init__(self, config): - self.base_url = config.host_url - self.proxy = config.proxy - if isinstance(config, SonarTokenConfig): self.authenticator = BearerTokenAuthenticator(config.user_token) - if isinstance(config, SonarUserPasswordConfig): + elif isinstance(config, SonarUserPasswordConfig): self.authenticator = UserPasswordBasicAuthenticator( config.username, config.password ) self.base_url = config.host_url else: - return TypeError("Unsupported configuration type.") + raise UnsupportedConfigurationError("Unsupported configuration type.") + + self.base_url = config.host_url + self.proxy = config.proxy def make_request(self, endpoint: str, method: str = "GET", **kwargs): url = f"{self.base_url}{endpoint}" diff --git a/metricheq/utils/__init__.py b/metricheq/exceptions/__init__.py similarity index 100% rename from metricheq/utils/__init__.py rename to metricheq/exceptions/__init__.py diff --git a/metricheq/exceptions/exceptions.py b/metricheq/exceptions/exceptions.py new file mode 100644 index 0000000..6a9b046 --- /dev/null +++ b/metricheq/exceptions/exceptions.py @@ -0,0 +1,2 @@ +class UnsupportedConfigurationError(Exception): + pass diff --git a/tests/github/__init__.py b/tests/github/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/github/test_github.py b/tests/github/test_github.py new file mode 100644 index 0000000..96fe5d7 --- /dev/null +++ b/tests/github/test_github.py @@ -0,0 +1,59 @@ +import unittest +from unittest.mock import Mock, patch + +import requests + +from metricheq.connectors.git_providers.github import ( + GitHubClient, + GitHubConfig, + GitHubConnector, +) + + +class TestGitHubClient(unittest.TestCase): + def setUp(self): + self.config = GitHubConfig(api_key="test_api_key") + + def test_initialization(self): + client = GitHubClient(self.config) + self.assertEqual(client.base_url, "https://api.github.com") + self.assertIsNotNone(client.authenticator) + + @patch("requests.Session.send") + def test_make_request(self, mock_send): + mock_response = Mock() + mock_response.status_code = 200 + mock_response.json.return_value = {"data": "test"} + mock_send.return_value = mock_response + + client = GitHubClient(self.config) + response = client.make_request("/test") + + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json(), {"data": "test"}) + + +class TestGitHubConnector(unittest.TestCase): + def setUp(self): + self.config = GitHubConfig(api_key="test_api_key") + + @patch("metricheq.connectors.git_providers.github.GitHubClient") + def test_connector_initialization(self, mock_client): + connector = GitHubConnector.from_config(self.config) + self.assertIsInstance(connector, GitHubConnector) + + @patch("metricheq.connectors.git_providers.github.GitHubClient.make_request") + def test_ensure_connectivity(self, mock_make_request): + mock_make_request.return_value.status_code = 200 + connector = GitHubConnector.from_config(self.config) + + connector.ensure_connectivity() + + @patch("metricheq.connectors.git_providers.github.GitHubClient.make_request") + def test_ensure_connectivity_failure(self, mock_make_request): + mock_make_request.side_effect = requests.RequestException + + connector = GitHubConnector.from_config(self.config) + + with self.assertRaises(ConnectionError): + connector.ensure_connectivity() diff --git a/tests/sonar/__init__.py b/tests/sonar/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/sonar/test_extractors.py b/tests/sonar/test_extractors.py new file mode 100644 index 0000000..f14dfc6 --- /dev/null +++ b/tests/sonar/test_extractors.py @@ -0,0 +1,18 @@ +import unittest +from unittest.mock import Mock, patch + +from metricheq.connectors.sonar import SonarConnector +from metricheq.extractors.sonar import SonarMeasuresExtractor, SonarMetricType + + +class TestSonarMeasuresExtractor(unittest.TestCase): + def setUp(self): + self.mock_connector = Mock(spec=SonarConnector) + self.mock_connector.client = Mock() + self.params = {"component": "my_component", "metric_key": SonarMetricType.BUGS} + + def test_initialization(self): + extractor = SonarMeasuresExtractor(self.mock_connector, self.params) + self.assertIsInstance(extractor, SonarMeasuresExtractor) + + # TODO: MORE TESTS diff --git a/tests/sonar/test_sonar.py b/tests/sonar/test_sonar.py new file mode 100644 index 0000000..e6adf8e --- /dev/null +++ b/tests/sonar/test_sonar.py @@ -0,0 +1,100 @@ +import unittest +from unittest.mock import Mock, patch + +import requests +from metricheq.connectors.base import ( + BearerTokenAuthenticator, + UserPasswordBasicAuthenticator, +) +from metricheq.connectors.sonar import ( + SonarClient, + SonarConnector, + SonarTokenConfig, + SonarUserPasswordConfig, +) +from metricheq.exceptions.exceptions import UnsupportedConfigurationError + + +class TestSonarClient(unittest.TestCase): + def test_init_with_token_config(self): + token_config = SonarTokenConfig( + host_url="http://example.com", user_token="abcd1234" + ) + + client = SonarClient(token_config) + + self.assertIsInstance(client.authenticator, BearerTokenAuthenticator) + + def test_init_with_user_password_config(self): + user_password_config = SonarUserPasswordConfig( + host_url="http://example.com", username="younes", password="1234" + ) + + client = SonarClient(user_password_config) + self.assertIsInstance(client.authenticator, UserPasswordBasicAuthenticator) + + def test_with_unsupported_config(self): + with self.assertRaises(UnsupportedConfigurationError): + SonarClient({}) + + @patch("requests.Session.send") + def test_make_request_success(self, mock_send): + mock_response = Mock() + mock_response.status_code = 200 + mock_response.json.return_value = {} + mock_send.return_value = mock_response + + config = SonarTokenConfig(host_url="http://example.com", user_token="token123") + client = SonarClient(config) + response = client.make_request("/api/test") + + self.assertEqual(response.status_code, 200) + + +class TestSonarConnector(unittest.TestCase): + @patch("metricheq.connectors.sonar.SonarClient") + def test_connector_initialization(self, mock_client): + connector = SonarConnector.from_config({}) + self.assertIsInstance(connector, SonarConnector) + + @patch("metricheq.connectors.sonar.SonarClient") + def test_ensure_connectivity(self, mock_client): + mock_client_instance = mock_client.return_value + mock_client_instance.make_request.return_value.json.return_value = { + "health": "GREEN" + } + + connector = SonarConnector(mock_client_instance) + self.assertTrue(connector.ensure_connectivity()) + + @patch("metricheq.connectors.sonar.SonarClient") + def test_connectivity_with_unhealthy_response(self, mock_client): + mock_client_instance = mock_client.return_value + mock_client_instance.make_request.return_value.json.return_value = { + "health": "RED" + } + + connector = SonarConnector(mock_client_instance) + with self.assertRaises(Exception): + connector.ensure_connectivity() + + @patch("metricheq.connectors.sonar.SonarClient") + def test_connectivity_with_request_exception(self, mock_client): + mock_client_instance = mock_client.return_value + mock_client_instance.make_request.side_effect = requests.RequestException + + connector = SonarConnector(mock_client_instance) + with self.assertRaises(ConnectionError): + connector.ensure_connectivity() + + @patch("metricheq.connectors.sonar.SonarClient") + def test_method_calls_with_mocks(self, mock_client): + mock_client_instance = mock_client.return_value + mock_client_instance.make_request.return_value.json.return_value = { + "health": "GREEN" + } + + connector = SonarConnector(mock_client_instance) + connector.ensure_connectivity() + + mock_client_instance.make_request.assert_called_once_with("/api/system/health") diff --git a/tests/test_evaluation.py b/tests/test_evaluation.py deleted file mode 100644 index 5b5adf5..0000000 --- a/tests/test_evaluation.py +++ /dev/null @@ -1,5 +0,0 @@ -import unittest - - -class Test(unittest.TestCase): - pass