From b044d3263baa55d1cdd837b452af431d26e64d53 Mon Sep 17 00:00:00 2001 From: Jennifer Power Date: Fri, 28 Jul 2023 14:59:34 -0400 Subject: [PATCH] test: adds unit tests to GitHub and GitLab providers Signed-off-by: Jennifer Power --- tests/trestlebot/test_cli.py | 2 ++ tests/trestlebot/test_github.py | 17 ++++++++++++++ tests/trestlebot/test_gitlab.py | 41 ++++++++++++++++++++++++++++++++- trestlebot/github.py | 32 ++++++++++++++----------- 4 files changed, 78 insertions(+), 14 deletions(-) diff --git a/tests/trestlebot/test_cli.py b/tests/trestlebot/test_cli.py index 283128a4..be6f1776 100644 --- a/tests/trestlebot/test_cli.py +++ b/tests/trestlebot/test_cli.py @@ -98,6 +98,8 @@ def test_with_target_branch(monkeypatch, valid_args_dict, capsys): args_dict["target-branch"] = "main" monkeypatch.setattr(sys, "argv", ["trestlebot", *args_dict_to_list(args_dict)]) + # Patch is_github_actions since these tests will be running in + # GitHub Actions with patch("trestlebot.cli.is_github_actions") as mock_check: mock_check.return_value = False diff --git a/tests/trestlebot/test_github.py b/tests/trestlebot/test_github.py index b0c523ab..8948cb11 100644 --- a/tests/trestlebot/test_github.py +++ b/tests/trestlebot/test_github.py @@ -17,6 +17,7 @@ """Test for GitHub provider logic""" from typing import Tuple +from unittest.mock import patch import pytest from git.repo import Repo @@ -70,3 +71,19 @@ def test_parse_repository_with_incorrect_name() -> None: match="https://notgithub.com/owner/repo.git is an invalid GitHub repo URL", ): gh.parse_repository("https://notgithub.com/owner/repo.git") + + +def test_create_pull_request_invalid_repo() -> None: + """Test triggering an error during pull request creation""" + gh = GitHub("fake") + with patch("github3.GitHub.repository") as mock_pull: + mock_pull.return_value = None + + with pytest.raises( + GitProviderException, + match="Repository for owner/repo cannot be None", + ): + gh.create_pull_request( + "owner", "repo", "main", "test", "My PR", "Has Changes" + ) + mock_pull.assert_called_once() diff --git a/tests/trestlebot/test_gitlab.py b/tests/trestlebot/test_gitlab.py index 2bf1689d..d0034d37 100644 --- a/tests/trestlebot/test_gitlab.py +++ b/tests/trestlebot/test_gitlab.py @@ -16,10 +16,12 @@ """Test for GitLab provider logic""" -from typing import Tuple +from typing import Callable, Tuple +from unittest.mock import patch import pytest from git.repo import Repo +from gitlab.exceptions import GitlabAuthenticationError, GitlabCreateError from tests.testutils import clean from trestlebot.gitlab import GitLab @@ -88,3 +90,40 @@ def test_parse_repository_with_incorrect_name() -> None: match="https://notgitlab.com/owner/repo.git is an invalid repo URL", ): gl.parse_repository("https://notgitlab.com/owner/repo.git") + + +def create_side_effect(name: str) -> None: + raise GitlabCreateError("example") + + +def auth_side_effect(name: str) -> None: + raise GitlabAuthenticationError("example") + + +@pytest.mark.parametrize( + "side_effect, msg", + [ + (create_side_effect, "Failed to create merge request in .*: example"), + ( + auth_side_effect, + "Authentication error during merge request creation in .*: example", + ), + ], +) +def test_create_pull_request_with_exceptions( + side_effect: Callable[[str], None], msg: str +) -> None: + """Test triggering an error during pull request creation""" + gl = GitLab("fake") + + with patch("gitlab.v4.objects.ProjectManager.get") as mock_get: + mock_get.side_effect = side_effect + + with pytest.raises( + GitProviderException, + match=msg, + ): + gl.create_pull_request( + "owner", "repo", "main", "test", "My PR", "Has Changes" + ) + mock_get.assert_called_once() diff --git a/trestlebot/github.py b/trestlebot/github.py index 893a617d..bcad53ca 100644 --- a/trestlebot/github.py +++ b/trestlebot/github.py @@ -21,6 +21,7 @@ from typing import Optional, Tuple import github3 +from github3.exceptions import AuthenticationFailed from github3.repos.repo import Repository from trestlebot.provider import GitProvider, GitProviderException @@ -85,23 +86,28 @@ def create_pull_request( Returns: Pull request number """ - repository: Optional[Repository] = self._session.repository( - owner=ns, repository=repo_name - ) - if repository is None: - raise GitProviderException( - f"Repository for {ns}/{repo_name} cannot be None" + try: + repository: Optional[Repository] = self._session.repository( + owner=ns, repository=repo_name ) + if repository is None: + raise GitProviderException( + f"Repository for {ns}/{repo_name} cannot be None" + ) - pull_request = repository.create_pull( - title=title, body=body, base=base_branch, head=head_branch - ) + pull_request = repository.create_pull( + title=title, body=body, base=base_branch, head=head_branch + ) - if pull_request: - return pull_request.number - else: + if pull_request: + return pull_request.number + else: + raise GitProviderException( + "Failed to create pull request in {ns}/{repo_name} for {head_branch} to {base_branch}" + ) + except AuthenticationFailed as e: raise GitProviderException( - "Failed to create pull request in {ns}/{repo_name} for {head_branch} to {base_branch}" + f"Authentication error during pull request creation in {ns}/{repo_name}: {e}" )