From 8fbc4e1151a530cc89cb76bf65e0d4525e05e173 Mon Sep 17 00:00:00 2001 From: amoghjalan Date: Thu, 18 Apr 2024 17:36:46 +0530 Subject: [PATCH] Add tests for _to_pr_model in GithubETLHandler --- .../service/code/sync/etl_github_handler.py | 3 +- apiserver/tests/factories/models/code.py | 8 +- .../tests/factories/models/exapi/github.py | 81 ++++++++ .../code/sync/test_etl_github_handler.py | 174 ++++++++++++++++++ 4 files changed, 263 insertions(+), 3 deletions(-) diff --git a/apiserver/dora/service/code/sync/etl_github_handler.py b/apiserver/dora/service/code/sync/etl_github_handler.py index 8cc7c6b36..a039fa108 100644 --- a/apiserver/dora/service/code/sync/etl_github_handler.py +++ b/apiserver/dora/service/code/sync/etl_github_handler.py @@ -270,10 +270,9 @@ def _get_merge_commit_sha(raw_data: Dict, state: PullRequestState) -> Optional[s return merge_commit_sha @staticmethod - def _get_state(pr: PullRequest) -> PullRequestState: + def _get_state(pr: GithubPullRequest) -> PullRequestState: if pr.merged_at: return PullRequestState.MERGED - if pr.closed_at: return PullRequestState.CLOSED diff --git a/apiserver/tests/factories/models/code.py b/apiserver/tests/factories/models/code.py index 465a81624..3ea2b7599 100644 --- a/apiserver/tests/factories/models/code.py +++ b/apiserver/tests/factories/models/code.py @@ -43,6 +43,8 @@ def get_pull_request( cycle_time=None, merge_to_deploy=None, lead_time=None, + url=None, + merge_commit_sha=None, ): return PullRequest( id=id or uuid4(), @@ -66,8 +68,12 @@ def get_pull_request( cycle_time=cycle_time, merge_to_deploy=merge_to_deploy, lead_time=lead_time, - reviewers=reviewers or ["randomuser1", "randomuser2"], + reviewers=reviewers + if reviewers is not None + else ["randomuser1", "randomuser2"], meta=meta or {}, + url=url, + merge_commit_sha=merge_commit_sha, ) diff --git a/apiserver/tests/factories/models/exapi/github.py b/apiserver/tests/factories/models/exapi/github.py index 0c3c71879..40487de29 100644 --- a/apiserver/tests/factories/models/exapi/github.py +++ b/apiserver/tests/factories/models/exapi/github.py @@ -1,3 +1,4 @@ +from collections import namedtuple from dataclasses import dataclass from datetime import datetime from typing import Dict @@ -52,3 +53,83 @@ def get_github_pull_request_review( ) -> GithubPullRequestReview: return GithubPullRequestReview(review_id, submitted_at, user_login) + + +Branch = namedtuple("Branch", ["ref"]) +User = namedtuple("User", ["login"]) + + +@dataclass +class GithubPullRequest: + number: int + merged_at: datetime + closed_at: datetime + title: str + html_url: str + created_at: datetime + updated_at: datetime + base: Branch + head: Branch + user: User + commits: int + additions: int + deletions: int + changed_files: int + merge_commit_sha: str + + @property + def raw_data(self): + return { + "number": self.number, + "merged_at": self.merged_at, + "closed_at": self.closed_at, + "title": self.title, + "html_url": self.html_url, + "created_at": self.created_at, + "updated_at": self.updated_at, + "base": {"ref": self.base.ref}, + "head": {"ref": self.head.ref}, + "user": {"login": self.user.login}, + "commits": self.commits, + "additions": self.additions, + "deletions": self.deletions, + "changed_files": self.changed_files, + "requested_reviewers": [], + "merge_commit_sha": self.merge_commit_sha, + } + + +def get_github_pull_request( + number: int = 1, + merged_at: datetime = None, + closed_at: datetime = None, + title: str = "random_title", + html_url: str = None, + created_at: datetime = time_now(), + updated_at: datetime = time_now(), + base_ref: str = "main", + head_ref: str = "feature", + user_login: str = "abc", + commits: int = 1, + additions: int = 1, + deletions: int = 1, + changed_files: int = 1, + merge_commit_sha: str = "123456", +) -> GithubPullRequest: + return GithubPullRequest( + number, + merged_at, + closed_at, + title, + html_url, + created_at, + updated_at, + Branch(base_ref), + Branch(head_ref), + User(user_login), + commits, + additions, + deletions, + changed_files, + merge_commit_sha, + ) diff --git a/apiserver/tests/service/code/sync/test_etl_github_handler.py b/apiserver/tests/service/code/sync/test_etl_github_handler.py index fb11c7180..287706717 100644 --- a/apiserver/tests/service/code/sync/test_etl_github_handler.py +++ b/apiserver/tests/service/code/sync/test_etl_github_handler.py @@ -3,6 +3,7 @@ import pytz from dora.service.code.sync.etl_github_handler import GithubETLHandler +from dora.store.models.code import PullRequestState from dora.utils.string import uuid4_str from tests.factories.models import ( get_pull_request, @@ -12,12 +13,185 @@ from tests.factories.models.exapi.github import ( get_github_commit_dict, get_github_pull_request_review, + get_github_pull_request, ) from tests.utilities import compare_objects_as_dicts ORG_ID = uuid4_str() +def test__to_pr_model_given_a_github_pr_returns_new_pr_model(): + repo_id = uuid4_str() + number = 123 + user_login = "abc" + merged_at = datetime(2022, 6, 29, 10, 53, 15, tzinfo=pytz.UTC) + head_branch = "feature" + base_branch = "main" + title = "random_title" + review_comments = 3 + merge_commit_sha = "123456789098765" + + github_pull_request = get_github_pull_request( + number=number, + merged_at=merged_at, + head_ref=head_branch, + base_ref=base_branch, + user_login=user_login, + merge_commit_sha=merge_commit_sha, + commits=3, + additions=10, + deletions=5, + changed_files=2, + ) + + github_etl_handler = GithubETLHandler(ORG_ID, None, None, None, None) + pr_model = github_etl_handler._to_pr_model( + pr=github_pull_request, + pr_model=None, + repo_id=repo_id, + review_comments=review_comments, + ) + + expected_pr_model = get_pull_request( + repo_id=repo_id, + number=str(number), + author=str(user_login), + state=PullRequestState.MERGED, + title=title, + head_branch=head_branch, + base_branch=base_branch, + provider="github", + requested_reviews=[], + data=github_pull_request.raw_data, + state_changed_at=merged_at, + meta={ + "code_stats": { + "commits": 3, + "additions": 10, + "deletions": 5, + "changed_files": 2, + "comments": review_comments, + }, + "user_profile": { + "username": user_login, + }, + }, + reviewers=[], + merge_commit_sha=merge_commit_sha, + ) + # Ignoring the following fields as they are generated as side effects and are not part of the actual data + # reviewers, rework_time, first_commit_to_open, first_response_time, lead_time, merge_time, merge_to_deploy, cycle_time + assert ( + compare_objects_as_dicts( + pr_model, + expected_pr_model, + [ + "id", + "created_at", + "updated_at", + "reviewers", + "rework_time", + "first_commit_to_open", + "first_response_time", + "lead_time", + "merge_time", + "merge_to_deploy", + "cycle_time", + ], + ) + is True + ) + + +def test__to_pr_model_given_a_github_pr_and_db_pr_returns_updated_pr_model(): + repo_id = uuid4_str() + number = 123 + user_login = "abc" + merged_at = datetime(2022, 6, 29, 10, 53, 15, tzinfo=pytz.UTC) + head_branch = "feature" + base_branch = "main" + title = "random_title" + review_comments = 3 + merge_commit_sha = "123456789098765" + + github_pull_request = get_github_pull_request( + number=number, + merged_at=merged_at, + head_ref=head_branch, + base_ref=base_branch, + user_login=user_login, + merge_commit_sha=merge_commit_sha, + commits=3, + additions=10, + deletions=5, + changed_files=2, + ) + + given_pr_model = get_pull_request( + repo_id=repo_id, + number=str(number), + provider="github", + ) + + github_etl_handler = GithubETLHandler(ORG_ID, None, None, None, None) + pr_model = github_etl_handler._to_pr_model( + pr=github_pull_request, + pr_model=given_pr_model, + repo_id=repo_id, + review_comments=review_comments, + ) + + expected_pr_model = get_pull_request( + id=given_pr_model.id, + repo_id=repo_id, + number=str(number), + author=str(user_login), + state=PullRequestState.MERGED, + title=title, + head_branch=head_branch, + base_branch=base_branch, + provider="github", + requested_reviews=[], + data=github_pull_request.raw_data, + state_changed_at=merged_at, + meta={ + "code_stats": { + "commits": 3, + "additions": 10, + "deletions": 5, + "changed_files": 2, + "comments": review_comments, + }, + "user_profile": { + "username": user_login, + }, + }, + reviewers=[], + merge_commit_sha=merge_commit_sha, + ) + # Ignoring the following fields as they are generated as side effects and are not part of the actual data + # reviewers, rework_time, first_commit_to_open, first_response_time, lead_time, merge_time, merge_to_deploy, cycle_time + assert ( + compare_objects_as_dicts( + pr_model, + expected_pr_model, + [ + "created_at", + "updated_at", + "reviewers", + "rework_time", + "first_commit_to_open", + "first_response_time", + "lead_time", + "merge_time", + "merge_to_deploy", + "cycle_time", + ], + ) + is True + ) + + def test__to_pr_events_given_an_empty_list_of_events_returns_an_empty_list(): pr_model = get_pull_request() assert GithubETLHandler._to_pr_events([], pr_model, []) == []