diff --git a/Makefile b/Makefile index 1a642c8..e00d27c 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ SHELL := /bin/bash -.PHONY: setup install install-dev lint test run clean-setup clean-lint all clean +.PHONY: setup install dev lint test run clean-setup clean-lint all clean -setup: install-dev +setup: dev uv run pre-commit install uv run pre-commit install --hook-type commit-msg diff --git a/README.md b/README.md index 8d00ba4..65248ec 100644 --- a/README.md +++ b/README.md @@ -9,12 +9,6 @@ Permissions needed for the Github Token: `Pull requests:read` `Pull requests:write` -If you have given `ANNOTATIONS_DATA_BRANCH` branch then Github Token also requires content write permissions. -Read more on how to use this [document](./docs/annotations.md). - -`Contents:read` -`Contents:write` - **install:** ```bash @@ -36,8 +30,8 @@ codecov - `GITHUB_REPOSITORY`: The name of the GitHub repository where the action is running. - `COVERAGE_PATH`: The path to the coverage report file. (JSON format) - `GITHUB_TOKEN`: The GitHub token used for authentication. -- `GITHUB_PR_NUMBER`: The number of the pull request where the action is running. (Optional) -- `GITHUB_REF`: The branch to run the action on. If not provided, it will be used to get the PR number. (Optional) +- `GITHUB_PR_NUMBER`: The number of the pull request where the coverage report comment to be generated. (Optional) +- `GITHUB_REF`: The branch name if pr number is not provided, it will be used to get the PR number. (Optional) Note: Either `GITHUB_PR_NUMBER` or `GITHUB_REF` is required. `GITHUB_PR_NUMBER` takes precedence if both mentioned. @@ -46,9 +40,6 @@ Note: Either `GITHUB_PR_NUMBER` or `GITHUB_REF` is required. `GITHUB_PR_NUMBER` - `MINIMUM_GREEN`: The minimum coverage percentage for green status. Default is 100. - `MINIMUM_ORANGE`: The minimum coverage percentage for orange status. Default is 70. - `BRANCH_COVERAGE`: Show branch coverage in the report. Default is False. -- `SKIP_COVERAGE`: Skip coverage reporting as github comment and generate only annotaions. Default is False. -- `ANNOTATIONS_DATA_BRANCH`: The branch to store the annotations. Read more about this [document](./docs/annotations.md). -- `ANNOTATIONS_OUTPUT_PATH`: The path where the annotaions should be stored. Should be a path to folder. - `ANNOTATE_MISSING_LINES`: Whether to annotate missing lines in the coverage report. Default is False. - `ANNOTATION_TYPE`: The type of annotation to use for missing lines. 'notice' or 'warning' or 'error'. Default is 'warning'. - `MAX_FILES_IN_COMMENT`: The maximum number of files to include in the coverage report comment. Default is 25. @@ -68,7 +59,7 @@ Note: Either `GITHUB_PR_NUMBER` or `GITHUB_REF` is required. `GITHUB_PR_NUMBER` project coverage, this may be expected. For consistent results, it is recommended to enable branch coverage when your report includes it. -## Setting up Local Environment using uv +## Dev Setup To get started, follow these steps: @@ -109,7 +100,7 @@ To get started, follow these steps: --- > **NOTE:** -> This project is almost copy of +> This project is inspired from > [py-cov-action/python-coverage-comment-action](), > [LICENSE]() with few modifications. --- diff --git a/codecov/badge.py b/codecov/badge.py index 151ab7f..29adc07 100644 --- a/codecov/badge.py +++ b/codecov/badge.py @@ -1,8 +1,3 @@ -""" -This module should contain only the things relevant to the badge being computed -by shields.io -""" - import decimal import urllib.parse diff --git a/codecov/config.py b/codecov/config.py index 659b8ca..4e77a16 100644 --- a/codecov/config.py +++ b/codecov/config.py @@ -53,11 +53,8 @@ class Config: TEST_FRAMEWORK: TestFramework = TestFramework.PYTEST # TODO: Remove branch coverage and just use the report BRANCH_COVERAGE: bool = False - SKIP_COVERAGE: bool = False # Deprecated ANNOTATE_MISSING_LINES: bool = False ANNOTATION_TYPE: AnnotationType = AnnotationType.WARNING - ANNOTATIONS_OUTPUT_PATH: pathlib.Path | None = None - ANNOTATIONS_DATA_BRANCH: str | None = None MAX_FILES_IN_COMMENT: int = 25 SKIP_COVERED_FILES_IN_REPORT: bool = True COMPLETE_PROJECT_REPORT: bool = False @@ -69,12 +66,6 @@ def __post_init__(self) -> None: if self.GITHUB_PR_NUMBER is None and self.GITHUB_REF is None: raise ValueError('Either GITHUB_PR_NUMBER or GITHUB_REF must be provided') - if self.SKIP_COVERAGE and not self.ANNOTATE_MISSING_LINES: - raise ValueError( - 'No action taken as both SKIP_COVERAGE and ANNOTATE_MISSING_LINES are set to False. \ - Neither comments nor annotations will be generated.' - ) - # Clean methods @classmethod def clean_minimum_green(cls, value: str) -> decimal.Decimal: @@ -88,10 +79,6 @@ def clean_minimum_orange(cls, value: str) -> decimal.Decimal: def clean_annotate_missing_lines(cls, value: str) -> bool: return str_to_bool(value) - @classmethod - def clean_skip_coverage(cls, value: str) -> bool: - return str_to_bool(value) - @classmethod def clean_branch_coverage(cls, value: str) -> bool: return str_to_bool(value) @@ -124,13 +111,6 @@ def clean_max_files_in_comment(cls, value: str) -> int: def clean_coverage_path(cls, value: str) -> pathlib.Path: return resolve_path(value) - @classmethod - def clean_annotations_output_path(cls, value: str) -> pathlib.Path: - path = pathlib.Path(value) - if path.exists() or path.is_dir(): - return path - raise ValueError - @classmethod def clean_test_framework(cls, value: str) -> TestFramework: return TestFramework(value) diff --git a/codecov/coverage/base.py b/codecov/coverage/base.py index 75dccf2..47d49a8 100644 --- a/codecov/coverage/base.py +++ b/codecov/coverage/base.py @@ -3,14 +3,12 @@ import json import pathlib from abc import ABC, abstractmethod -from typing import Any +from typing import Any, ClassVar from codecov.config import Config, TestFramework from codecov.exceptions import ConfigurationException from codecov.log import log -COVERAGE_HANDLER_REGISTRY: dict[TestFramework, type['BaseCoverageHandler']] = {} - @dataclasses.dataclass class FileDiffCoverage: @@ -35,9 +33,10 @@ class DiffCoverage: class BaseCoverageHandler(ABC): TEST_FRAMEWORK: TestFramework + REGISTRY: ClassVar[dict[TestFramework, type['BaseCoverageHandler']]] = {} def __init_subclass__(cls) -> None: - COVERAGE_HANDLER_REGISTRY[cls.TEST_FRAMEWORK] = cls + cls.REGISTRY[cls.TEST_FRAMEWORK] = cls super().__init_subclass__() def convert_to_decimal(self, value: float | decimal.Decimal, precision: int = 2) -> decimal.Decimal: @@ -86,7 +85,7 @@ def get_diff_coverage( @classmethod def get_coverage_handler(cls, test_framework: TestFramework) -> type['BaseCoverageHandler']: try: - return COVERAGE_HANDLER_REGISTRY[test_framework] + return cls.REGISTRY[test_framework] except KeyError as exc: log.error('No coverage handler found for test framework: %s', test_framework.value) raise ConfigurationException from exc diff --git a/codecov/exceptions.py b/codecov/exceptions.py index e436af6..acdcf64 100644 --- a/codecov/exceptions.py +++ b/codecov/exceptions.py @@ -18,10 +18,6 @@ class CannotGetUser(GithubBaseException): pass -class CannotGetBranch(GithubBaseException): - pass - - class CannotPostComment(GithubBaseException): pass diff --git a/codecov/github.py b/codecov/github.py index 4454f04..0726645 100644 --- a/codecov/github.py +++ b/codecov/github.py @@ -4,22 +4,16 @@ from codecov.exceptions import ( ApiError, - CannotGetBranch, CannotGetPullRequest, CannotGetUser, CannotPostComment, - Conflict, Forbidden, NotFound, Unauthorized, - ValidationFailed, ) from codecov.github_client import GitHubClient -from codecov.groups import Annotation from codecov.log import log -COMMIT_MESSAGE = 'Update annotations data' - @dataclasses.dataclass class User: @@ -29,17 +23,9 @@ class User: class Github: - def __init__( # pylint: disable=too-many-arguments, too-many-positional-arguments - self, - client: GitHubClient, - repository: str, - pr_number: int | None = None, - ref: str | None = None, - annotations_data_branch: str = None, - ): + def __init__(self, client: GitHubClient, repository: str, pr_number: int | None = None, ref: str | None = None): self.client = client self.repository: str = repository - self.annotations_data_branch: str | None = annotations_data_branch self.user: User = self._init_user() self.pr_number, self.base_ref = self._init_pr_number(pr_number=pr_number, ref=ref) @@ -188,92 +174,6 @@ def post_comment(self, contents: str, marker: str) -> None: ) raise CannotPostComment from exc - def write_annotations_to_branch(self, annotations: list[Annotation]) -> None: - if not self.annotations_data_branch: - log.debug('No annotations data branch provided. Exiting.') - return - - log.debug('Getting the annotations data branch.') - try: - data_branch = self.client.repos(self.repository).branches(self.annotations_data_branch).get() - if data_branch.protected: - log.debug('Branch "%s/%s" is protected.', self.repository, self.annotations_data_branch) - raise NotFound - except Forbidden as exc: - log.error( - 'Insufficient permissions to write annotations to the branch "%s/%s". Please verify the token permissions and ensure it has content read and write access.', - self.repository, - self.annotations_data_branch, - ) - raise CannotGetBranch from exc - except NotFound as exc: - log.error( - 'Branch "%s/%s" either does not exist or is protected.', self.repository, self.annotations_data_branch - ) - raise CannotGetBranch from exc - - log.info('Writing annotations to branch.') - file_name = f'{self.pr_number}-annotations.json' - file_sha: str | None = None - try: - file = self.client.repos(self.repository).contents(file_name).get(ref=self.annotations_data_branch) - file_sha = file.sha - except NotFound: - log.debug( - 'File "%s" does not exist in branch "%s/%s", creating new file.', - file_name, - self.repository, - self.annotations_data_branch, - ) - except Forbidden as exc: - log.error( - 'Insufficient permissions to write annotations to the branch "%s/%s". Please verify the token permissions and ensure it has content read and write access.', - self.repository, - self.annotations_data_branch, - ) - raise CannotGetBranch from exc - - try: - log.debug('Writing annotations to file to branch.') - encoded_content = Annotation.encode(annotations) - self.client.repos(self.repository).contents(file_name).put( - message=COMMIT_MESSAGE, - branch=self.annotations_data_branch, - sha=file_sha, - committer={ - 'name': self.user.name, - 'email': self.user.email, - }, - content=encoded_content, - ) - except NotFound as exc: - log.error( - 'Branch "%s/%s" either does not exist or is protected.', self.repository, self.annotations_data_branch - ) - raise CannotGetBranch from exc - except Forbidden as exc: - log.error( - 'Insufficient permissions to write annotations to the branch "%s/%s". Please verify the token permissions and ensure it has content read and write access.', - self.repository, - self.annotations_data_branch, - ) - raise CannotGetBranch from exc - except Conflict as exc: - log.error( - 'Conflict while adding #%s pull request annotation to branch "%s/%s".', - self.pr_number, - self.repository, - self.annotations_data_branch, - ) - raise CannotGetBranch from exc - except ValidationFailed as exc: - log.error( - 'Validation failed for committer name or email, or the endpoint was spammed while writing annotation to branch "%s/%s".', - self.repository, - self.annotations_data_branch, - ) - raise CannotGetBranch from exc - class GithubDiffParser: def __init__(self, diff: str): diff --git a/codecov/groups.py b/codecov/groups.py index 0f0e04c..e2db9e6 100644 --- a/codecov/groups.py +++ b/codecov/groups.py @@ -1,11 +1,8 @@ -import base64 import dataclasses import functools import itertools -import json import pathlib from collections.abc import Iterable -from typing import Self @dataclasses.dataclass(frozen=True) @@ -15,13 +12,6 @@ class Group: line_end: int -class AnnotationEncoder(json.JSONEncoder): - def default(self, o): - if isinstance(o, Annotation): - return o.to_dict() - return super().default(o) - - @dataclasses.dataclass class Annotation: file: pathlib.Path @@ -47,10 +37,6 @@ def to_dict(self): 'message': self.message, } - @classmethod - def encode(cls, annotations: list[Self]) -> str: - return base64.b64encode(json.dumps(annotations, cls=AnnotationEncoder).encode()).decode() - def create_missing_coverage_annotations( annotation_type: str, diff --git a/codecov/main.py b/codecov/main.py index 0e1f43a..e40be18 100644 --- a/codecov/main.py +++ b/codecov/main.py @@ -1,4 +1,3 @@ -import json import os from typing import cast @@ -37,7 +36,6 @@ def _init_github(self) -> Github: repository=self.config.GITHUB_REPOSITORY, pr_number=self.config.GITHUB_PR_NUMBER, ref=self.config.GITHUB_REF, - annotations_data_branch=self.config.ANNOTATIONS_DATA_BRANCH, ) return github @@ -50,7 +48,6 @@ def _init_coverage_module(self) -> BaseCoverageHandler: def run(self): self._process_coverage() - self._render_comment_markdown() self._create_comment() self._generate_annotations() @@ -73,11 +70,7 @@ def _get_coverage(self) -> PytestCoverage | JestCoverage: log.error('Error parsing the coverage file. Please check the file and try again.') raise CoreProcessingException from e - def _render_comment_markdown(self) -> None: - if self.config.SKIP_COVERAGE: - log.info('Skipping coverage report generation.') - return - + def _create_comment(self) -> None: log.info('Generating comment for PR #%s', self.github.pr_number) diff_files_info, diff_count_files = template.select_changed_files( coverage=self.coverage, @@ -124,14 +117,11 @@ def _render_comment_markdown(self) -> None: ) raise CoreProcessingException from e - self.comment = comment - - def _create_comment(self): - if not self.comment: + if not comment: log.error('Failed to generate comment, rendered template is empty.') raise CoreProcessingException - self.github.post_comment(contents=self.comment, marker=self.marker) + self.github.post_comment(contents=comment, marker=self.marker) log.info('Comment created on PR.') def _generate_annotations(self): @@ -170,16 +160,3 @@ def _generate_annotations(self): print(yellow, end='') print(*formatted_annotations, sep='\n') print(reset, end='') - - # Save to file - file_name = f'{self.github.pr_number}-annotations.json' - if self.config.ANNOTATIONS_OUTPUT_PATH: - log.info('Writing annotations to file %s', file_name) - with self.config.ANNOTATIONS_OUTPUT_PATH.joinpath(file_name).open('w+') as annotations_file: - json.dump(formatted_annotations, annotations_file, cls=groups.AnnotationEncoder) - - # Write to branch - if self.config.ANNOTATIONS_DATA_BRANCH: - log.info('Writing annotations to branch.') - self.github.write_annotations_to_branch(annotations=formatted_annotations) - log.info('Annotations generated.') diff --git a/codecov/template.py b/codecov/template.py index dbeda09..5f754ed 100644 --- a/codecov/template.py +++ b/codecov/template.py @@ -225,7 +225,7 @@ def get_file_url( # pylint: disable=too-many-arguments s = f'https://github.com/{repo_name}/pull/{pr_number}/files#diff-{hashlib.sha256(str(filename).encode("utf-8")).hexdigest()}' if lines is not None: - # R stands for Right side of the diff. But since we generate these links for new code we only need the right side. + # R stands for Right side of the diff. Since we generate these links for new code, we only need the right side. s += f'R{lines[0]}-R{lines[1]}' return s diff --git a/docs/annotations.md b/docs/annotations.md deleted file mode 100644 index d7d6ba0..0000000 --- a/docs/annotations.md +++ /dev/null @@ -1,31 +0,0 @@ -# How Annotations Work - -Annotations in this context are similar to GitHub annotations or workflow commands, -displaying a banner in the GitHub pull request. -When the option `ANNOTATE_MISSING_LINES=True` is enabled, annotations are generated for lines missing coverage. -To include branch coverage in these annotations, enable `BRANCH_COVERAGE=True`. -By default, these annotations are written to the console, but you can also choose to save them elsewhere. - -## Storing Annotations - -1. **To a Folder**: - - Set the folder path in `ANNOTATIONS_OUTPUT_PATH`. - -2. **To a Branch**: - - Set the branch name in `ANNOTATIONS_DATA_BRANCH`. - - Ensure your GitHub token has `Contents:write` permissions. - - Make sure the branch exists and is not protected by branch protection rules. - - Annotations are stored with the filename `{PR-number}-annotations.json`, - where `{PR-number}` is replaced by the actual PR number. - - Existing annotations for a PR in the branch will be overwritten if the file already exist in branch. - - If the GitHub token user has email privacy enabled, the email format `{id}+{login}@users.noreply.github.com` is used. - Where `{id}` is the user ID and `{login}` is the username. - -## Using the Annotations - -After generating the annotations, you can enable this extension. -A URL is required where the annotations are accessible from the extension, with a placeholder for the PR number. -For example: -`https://raw.githubusercontent.com/PradeepTammali/python-coverage-comment/data/coverage-annotations/{PR-NUMBER}-annotations.json` - -The `{PR-NUMBER}` placeholder will be replaced with the actual PR number when viewing the PR diff. diff --git a/tests/conftest.py b/tests/conftest.py index 3887554..3a9e728 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,7 +1,5 @@ -# pylint: disable=redefined-outer-name # mypy: disable-error-code="operator, union-attr" - import dataclasses import datetime import decimal @@ -419,7 +417,6 @@ def gh(gh_client, test_config: Config): github_mock = MagicMock() github_mock.client = gh_client github_mock.repository = test_config.GITHUB_REPOSITORY - github_mock.annotations_data_branch = test_config.ANNOTATIONS_DATA_BRANCH github_mock.pr_number = test_config.GITHUB_PR_NUMBER github_mock.base_ref = test_config.GITHUB_REF github_mock.pr_diff = 'diff --git a/codebase/code.py b/codebase/code.py\nindex 0000000..1111111 100644\n--- a/codebase/code.py\n+++ b/codebase/code.py\n@@ -1,2 +1,3 @@\n+line added\n line covered\n line covered\n' diff --git a/tests/test_config.py b/tests/test_config.py index e883908..5af7db5 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -42,42 +42,37 @@ def test_config_from_environ_missing(): def test_config_from_environ_sample(): token = secrets.token_urlsafe() with tempfile.NamedTemporaryFile(suffix='.json') as temp_file: - with tempfile.TemporaryDirectory() as tmp_dir: - assert config.Config.from_environ( - { - 'GITHUB_REPOSITORY': 'your_repository', - 'COVERAGE_PATH': temp_file.name, - 'GITHUB_TOKEN': token, - 'GITHUB_PR_NUMBER': '123', - 'GITHUB_REF': 'main', - 'MINIMUM_GREEN': '90', - 'MINIMUM_ORANGE': '70', - 'SKIP_COVERAGE': 'False', - 'ANNOTATE_MISSING_LINES': 'True', - 'ANNOTATION_TYPE': 'notice', - 'ANNOTATIONS_OUTPUT_PATH': str(tmp_dir), - 'MAX_FILES_IN_COMMENT': 25, - 'COMPLETE_PROJECT_REPORT': 'True', - 'COVERAGE_REPORT_URL': 'https://your_coverage_report_url', - 'DEBUG': 'False', - } - ) == config.Config( - GITHUB_REPOSITORY='your_repository', - COVERAGE_PATH=pathlib.Path(temp_file.name).resolve(), - GITHUB_TOKEN=token, # noqa: S106 - GITHUB_PR_NUMBER=123, - GITHUB_REF='main', - MINIMUM_GREEN=decimal.Decimal('90'), - MINIMUM_ORANGE=decimal.Decimal('70'), - SKIP_COVERAGE=False, - ANNOTATE_MISSING_LINES=True, - ANNOTATION_TYPE=config.AnnotationType.NOTICE, - ANNOTATIONS_OUTPUT_PATH=pathlib.Path(tmp_dir), - MAX_FILES_IN_COMMENT=25, - COMPLETE_PROJECT_REPORT=True, - COVERAGE_REPORT_URL='https://your_coverage_report_url', - DEBUG=False, - ) + assert config.Config.from_environ( + { + 'GITHUB_REPOSITORY': 'your_repository', + 'COVERAGE_PATH': temp_file.name, + 'GITHUB_TOKEN': token, + 'GITHUB_PR_NUMBER': '123', + 'GITHUB_REF': 'main', + 'MINIMUM_GREEN': '90', + 'MINIMUM_ORANGE': '70', + 'ANNOTATE_MISSING_LINES': 'True', + 'ANNOTATION_TYPE': 'notice', + 'MAX_FILES_IN_COMMENT': 25, + 'COMPLETE_PROJECT_REPORT': 'True', + 'COVERAGE_REPORT_URL': 'https://your_coverage_report_url', + 'DEBUG': 'False', + } + ) == config.Config( + GITHUB_REPOSITORY='your_repository', + COVERAGE_PATH=pathlib.Path(temp_file.name).resolve(), + GITHUB_TOKEN=token, # noqa: S106 + GITHUB_PR_NUMBER=123, + GITHUB_REF='main', + MINIMUM_GREEN=decimal.Decimal('90'), + MINIMUM_ORANGE=decimal.Decimal('70'), + ANNOTATE_MISSING_LINES=True, + ANNOTATION_TYPE=config.AnnotationType.NOTICE, + MAX_FILES_IN_COMMENT=25, + COMPLETE_PROJECT_REPORT=True, + COVERAGE_REPORT_URL='https://your_coverage_report_url', + DEBUG=False, + ) def test_config_required_pr_or_ref(): @@ -130,11 +125,6 @@ def test_config_clean_annotate_missing_lines(): assert value is True -def test_config_clean_skip_coverage(): - value = config.Config.clean_skip_coverage('False') - assert value is False - - def test_config_clean_branch_coverage(): value = config.Config.clean_branch_coverage('False') assert value is False @@ -176,15 +166,6 @@ def test_config_clean_coverage_path(): assert value == pathlib.Path(temp_file.name).resolve() -def test_config_clean_annotations_output_path(): - with tempfile.TemporaryDirectory() as temp_dir: - value = config.Config.clean_annotations_output_path(temp_dir) - assert value == pathlib.Path(temp_dir) - - with pytest.raises(ValueError): - config.Config.clean_annotations_output_path('/path/to/nonexistent_dir') - - def test_str_to_bool_invalid(): assert config.str_to_bool('invalid') is False diff --git a/tests/test_github.py b/tests/test_github.py index 9427f7f..85c3145 100644 --- a/tests/test_github.py +++ b/tests/test_github.py @@ -1,13 +1,10 @@ -import base64 -import json import pathlib from unittest.mock import MagicMock, patch import pytest -from codecov.exceptions import CannotGetBranch, CannotGetPullRequest, CannotGetUser, CannotPostComment -from codecov.github import COMMIT_MESSAGE, Github, GithubDiffParser, User -from codecov.groups import Annotation, AnnotationEncoder +from codecov.exceptions import CannotGetPullRequest, CannotGetUser, CannotPostComment +from codecov.github import Github, GithubDiffParser, User TEST_DATA_PR_DIFF = 'diff --git a/file.py b/file.py\nindex 1234567..abcdefg 100644\n--- a/file.py\n+++ b/file.py\n@@ -1,2 +1,2 @@\n-foo\n+bar\n-baz\n+qux\n' @@ -29,11 +26,9 @@ def test_init( repository=test_config.GITHUB_REPOSITORY, pr_number=test_config.GITHUB_PR_NUMBER, ref=test_config.GITHUB_REF, - annotations_data_branch=test_config.ANNOTATIONS_DATA_BRANCH, ) assert gh.client == gh_client assert gh.repository == test_config.GITHUB_REPOSITORY - assert gh.annotations_data_branch == test_config.ANNOTATIONS_DATA_BRANCH assert gh.user == User(name='bar', email='baz@foobar.com', login='foo') assert gh.pr_number == test_config.GITHUB_PR_NUMBER assert gh.base_ref == 'feature/branch' @@ -59,7 +54,6 @@ def test_init_user_login( repository=test_config.GITHUB_REPOSITORY, pr_number=test_config.GITHUB_PR_NUMBER, ref=test_config.GITHUB_REF, - annotations_data_branch=test_config.ANNOTATIONS_DATA_BRANCH, ) gh_init_pr_number_mock.assert_not_called() gh_init_pr_diff_mock.assert_not_called() @@ -71,7 +65,6 @@ def test_init_user_login( repository=test_config.GITHUB_REPOSITORY, pr_number=test_config.GITHUB_PR_NUMBER, ref=test_config.GITHUB_REF, - annotations_data_branch=test_config.ANNOTATIONS_DATA_BRANCH, ) gh_init_pr_number_mock.assert_not_called() gh_init_pr_diff_mock.assert_not_called() @@ -82,7 +75,6 @@ def test_init_user_login( repository=test_config.GITHUB_REPOSITORY, pr_number=test_config.GITHUB_PR_NUMBER, ref=test_config.GITHUB_REF, - annotations_data_branch=test_config.ANNOTATIONS_DATA_BRANCH, ) assert gh.user == User(name='bar', email='baz', login='foo') gh_init_pr_number_mock.assert_called_once() @@ -102,7 +94,6 @@ def test_init_pr_number( Github( client=gh_client, repository=test_config.GITHUB_REPOSITORY, - annotations_data_branch=test_config.ANNOTATIONS_DATA_BRANCH, ) gh_init_user_mock.assert_called_once() gh_init_pr_diff_mock.assert_not_called() @@ -116,7 +107,6 @@ def test_init_pr_number( client=gh_client, repository=test_config.GITHUB_REPOSITORY, pr_number=test_config.GITHUB_PR_NUMBER, - annotations_data_branch=test_config.ANNOTATIONS_DATA_BRANCH, ) gh_init_user_mock.assert_called_once() gh_init_pr_diff_mock.assert_not_called() @@ -130,7 +120,6 @@ def test_init_pr_number( client=gh_client, repository=test_config.GITHUB_REPOSITORY, pr_number=test_config.GITHUB_PR_NUMBER, - annotations_data_branch=test_config.ANNOTATIONS_DATA_BRANCH, ) gh_init_user_mock.assert_called_once() gh_init_pr_diff_mock.assert_not_called() @@ -144,7 +133,6 @@ def test_init_pr_number( client=gh_client, repository=test_config.GITHUB_REPOSITORY, pr_number=test_config.GITHUB_PR_NUMBER, - annotations_data_branch=test_config.ANNOTATIONS_DATA_BRANCH, ) gh_init_user_mock.assert_called_once() gh_init_pr_diff_mock.assert_not_called() @@ -157,7 +145,6 @@ def test_init_pr_number( client=gh_client, repository=test_config.GITHUB_REPOSITORY, pr_number=test_config.GITHUB_PR_NUMBER, - annotations_data_branch=test_config.ANNOTATIONS_DATA_BRANCH, ) assert gh.pr_number == test_config.GITHUB_PR_NUMBER assert gh.base_ref == 'feature/branch' @@ -181,7 +168,6 @@ def test_init_pr_ref( client=gh_client, repository=test_config.GITHUB_REPOSITORY, ref=test_config.GITHUB_REF, - annotations_data_branch=test_config.ANNOTATIONS_DATA_BRANCH, ) gh_init_user_mock.assert_called_once() gh_init_pr_diff_mock.assert_not_called() @@ -193,7 +179,6 @@ def test_init_pr_ref( client=gh_client, repository=test_config.GITHUB_REPOSITORY, ref=test_config.GITHUB_REF, - annotations_data_branch=test_config.ANNOTATIONS_DATA_BRANCH, ) gh_init_user_mock.assert_called_once() gh_init_pr_diff_mock.assert_not_called() @@ -205,7 +190,6 @@ def test_init_pr_ref( client=gh_client, repository=test_config.GITHUB_REPOSITORY, ref=test_config.GITHUB_REF, - annotations_data_branch=test_config.ANNOTATIONS_DATA_BRANCH, ) gh_init_user_mock.assert_called_once() gh_init_pr_diff_mock.assert_not_called() @@ -221,7 +205,6 @@ def test_init_pr_ref( client=gh_client, repository=test_config.GITHUB_REPOSITORY, ref=test_config.GITHUB_REF, - annotations_data_branch=test_config.ANNOTATIONS_DATA_BRANCH, ) assert gh.pr_number == test_config.GITHUB_PR_NUMBER gh_init_user_mock.assert_called_once() @@ -245,7 +228,6 @@ def test_init_pr_diff( client=gh_client, repository=test_config.GITHUB_REPOSITORY, pr_number=test_config.GITHUB_PR_NUMBER, - annotations_data_branch=test_config.ANNOTATIONS_DATA_BRANCH, ) gh_init_user_mock.assert_called_once() gh_init_pr_number_mock.assert_called_once() @@ -260,7 +242,6 @@ def test_init_pr_diff( client=gh_client, repository=test_config.GITHUB_REPOSITORY, pr_number=test_config.GITHUB_PR_NUMBER, - annotations_data_branch=test_config.ANNOTATIONS_DATA_BRANCH, ) gh_init_user_mock.assert_called_once() gh_init_pr_number_mock.assert_called_once() @@ -274,7 +255,6 @@ def test_init_pr_diff( client=gh_client, repository=test_config.GITHUB_REPOSITORY, pr_number=test_config.GITHUB_PR_NUMBER, - annotations_data_branch=test_config.ANNOTATIONS_DATA_BRANCH, ) assert gh.pr_diff == TEST_DATA_PR_DIFF gh_init_user_mock.assert_called_once() @@ -297,7 +277,6 @@ def test_post_comment( client=gh_client, repository=test_config.GITHUB_REPOSITORY, pr_number=test_config.GITHUB_PR_NUMBER, - annotations_data_branch=test_config.ANNOTATIONS_DATA_BRANCH, ).post_comment(contents='a' * 65537, marker='marker') gh_init_user_mock.assert_called_once() gh_init_pr_number_mock.assert_called_once() @@ -319,7 +298,6 @@ def test_post_comment( client=gh_client, repository=test_config.GITHUB_REPOSITORY, pr_number=test_config.GITHUB_PR_NUMBER, - annotations_data_branch=test_config.ANNOTATIONS_DATA_BRANCH, ).post_comment(contents='hi!', marker='marker') gh_init_user_mock.assert_called_once() gh_init_pr_number_mock.assert_called_once() @@ -340,7 +318,6 @@ def test_post_comment( client=gh_client, repository=test_config.GITHUB_REPOSITORY, pr_number=test_config.GITHUB_PR_NUMBER, - annotations_data_branch=test_config.ANNOTATIONS_DATA_BRANCH, ) gh.post_comment(contents='hi!', marker='marker') gh_init_user_mock.assert_called_once() @@ -382,7 +359,6 @@ def test_post_comment_update( client=gh_client, repository=test_config.GITHUB_REPOSITORY, pr_number=test_config.GITHUB_PR_NUMBER, - annotations_data_branch=test_config.ANNOTATIONS_DATA_BRANCH, ).post_comment(contents='hi!', marker='marker') gh_init_user_mock.assert_called_once() gh_init_pr_number_mock.assert_called_once() @@ -404,7 +380,6 @@ def test_post_comment_update( client=gh_client, repository=test_config.GITHUB_REPOSITORY, pr_number=test_config.GITHUB_PR_NUMBER, - annotations_data_branch=test_config.ANNOTATIONS_DATA_BRANCH, ).post_comment(contents='hi!', marker='marker') gh_init_user_mock.assert_called_once() gh_init_pr_number_mock.assert_called_once() @@ -425,244 +400,12 @@ def test_post_comment_update( client=gh_client, repository=test_config.GITHUB_REPOSITORY, pr_number=test_config.GITHUB_PR_NUMBER, - annotations_data_branch=test_config.ANNOTATIONS_DATA_BRANCH, ) gh.post_comment(contents='hi!', marker='marker') gh_init_user_mock.assert_called_once() gh_init_pr_number_mock.assert_called_once() gh_init_pr_diff_mock.assert_called_once() - @patch.object(Github, '_init_pr_diff', return_value=TEST_DATA_PR_DIFF) - @patch.object(Github, '_init_pr_number', return_value=(123, 'feature/branch')) - @patch.object(Github, '_init_user', return_value=User(name='bar', email='baz@foobar.com', login='foo')) - def test_write_annotations_to_branch( - self, - gh_init_user_mock: MagicMock, - gh_init_pr_number_mock: MagicMock, - gh_init_pr_diff_mock: MagicMock, - session, - test_config, - gh_client, - ): - Github( - client=gh_client, - repository=test_config.GITHUB_REPOSITORY, - pr_number=test_config.GITHUB_PR_NUMBER, - annotations_data_branch=test_config.ANNOTATIONS_DATA_BRANCH, - ).write_annotations_to_branch(annotations=[]) - gh_init_user_mock.assert_called_once() - gh_init_pr_number_mock.assert_called_once() - gh_init_pr_diff_mock.assert_called_once() - gh_init_user_mock.reset_mock() - gh_init_pr_number_mock.reset_mock() - gh_init_pr_diff_mock.reset_mock() - - test_config.ANNOTATIONS_DATA_BRANCH = 'annotations' - gh = Github( - client=gh_client, - repository=test_config.GITHUB_REPOSITORY, - pr_number=test_config.GITHUB_PR_NUMBER, - annotations_data_branch=test_config.ANNOTATIONS_DATA_BRANCH, - ) - session.register( - 'GET', f'/repos/{test_config.GITHUB_REPOSITORY}/branches/{test_config.ANNOTATIONS_DATA_BRANCH}' - )(json={'protected': True}) - with pytest.raises(CannotGetBranch): - gh.write_annotations_to_branch(annotations=[]) - gh_init_user_mock.assert_called_once() - gh_init_pr_number_mock.assert_called_once() - gh_init_pr_diff_mock.assert_called_once() - - session.register( - 'GET', f'/repos/{test_config.GITHUB_REPOSITORY}/branches/{test_config.ANNOTATIONS_DATA_BRANCH}' - )(status_code=403) - with pytest.raises(CannotGetBranch): - gh.write_annotations_to_branch(annotations=[]) - gh_init_user_mock.assert_called_once() - gh_init_pr_number_mock.assert_called_once() - gh_init_pr_diff_mock.assert_called_once() - - session.register( - 'GET', f'/repos/{test_config.GITHUB_REPOSITORY}/branches/{test_config.ANNOTATIONS_DATA_BRANCH}' - )(status_code=404) - with pytest.raises(CannotGetBranch): - gh.write_annotations_to_branch(annotations=[]) - gh_init_user_mock.assert_called_once() - gh_init_pr_number_mock.assert_called_once() - gh_init_pr_diff_mock.assert_called_once() - - session.register( - 'GET', f'/repos/{test_config.GITHUB_REPOSITORY}/branches/{test_config.ANNOTATIONS_DATA_BRANCH}' - )(json={'protected': False, 'name': test_config.ANNOTATIONS_DATA_BRANCH}) - session.register( - 'GET', - f'/repos/{test_config.GITHUB_REPOSITORY}/contents/{test_config.GITHUB_PR_NUMBER}-annotations.json', - params={'ref': test_config.ANNOTATIONS_DATA_BRANCH}, - )(status_code=403) - with pytest.raises(CannotGetBranch): - gh.write_annotations_to_branch(annotations=[]) - gh_init_user_mock.assert_called_once() - gh_init_pr_number_mock.assert_called_once() - gh_init_pr_diff_mock.assert_called_once() - - annotations = [ - Annotation( - file=pathlib.Path('file.py'), - line_start=10, - line_end=10, - title='Error', - message_type='warning', - message='Error', - ) - ] - session.register( - 'GET', f'/repos/{test_config.GITHUB_REPOSITORY}/branches/{test_config.ANNOTATIONS_DATA_BRANCH}' - )(json={'protected': False, 'name': test_config.ANNOTATIONS_DATA_BRANCH}) - session.register( - 'GET', - f'/repos/{test_config.GITHUB_REPOSITORY}/contents/{test_config.GITHUB_PR_NUMBER}-annotations.json', - params={'ref': test_config.ANNOTATIONS_DATA_BRANCH}, - )(status_code=404) - session.register( - 'PUT', - f'/repos/{test_config.GITHUB_REPOSITORY}/contents/{test_config.GITHUB_PR_NUMBER}-annotations.json', - json={ - 'message': COMMIT_MESSAGE, - 'branch': test_config.ANNOTATIONS_DATA_BRANCH, - 'sha': None, - 'committer': {'name': gh.user.name, 'email': gh.user.email}, - 'content': base64.b64encode(json.dumps(annotations, cls=AnnotationEncoder).encode()).decode(), - }, - )(json={'content': {'sha': 'abc'}}) - gh.write_annotations_to_branch(annotations=annotations) - gh_init_user_mock.assert_called_once() - gh_init_pr_number_mock.assert_called_once() - gh_init_pr_diff_mock.assert_called_once() - - session.register( - 'GET', f'/repos/{test_config.GITHUB_REPOSITORY}/branches/{test_config.ANNOTATIONS_DATA_BRANCH}' - )(json={'protected': False, 'name': test_config.ANNOTATIONS_DATA_BRANCH}) - session.register( - 'GET', - f'/repos/{test_config.GITHUB_REPOSITORY}/contents/{test_config.GITHUB_PR_NUMBER}-annotations.json', - params={'ref': test_config.ANNOTATIONS_DATA_BRANCH}, - )(json={'sha': 'abc'}) - session.register( - 'PUT', - f'/repos/{test_config.GITHUB_REPOSITORY}/contents/{test_config.GITHUB_PR_NUMBER}-annotations.json', - json={ - 'message': COMMIT_MESSAGE, - 'branch': test_config.ANNOTATIONS_DATA_BRANCH, - 'sha': 'abc', - 'committer': {'name': gh.user.name, 'email': gh.user.email}, - 'content': base64.b64encode(json.dumps(annotations, cls=AnnotationEncoder).encode()).decode(), - }, - )(json={'content': {'sha': 'abc'}}) - gh.write_annotations_to_branch(annotations=annotations) - gh_init_user_mock.assert_called_once() - gh_init_pr_number_mock.assert_called_once() - gh_init_pr_diff_mock.assert_called_once() - - session.register( - 'GET', f'/repos/{test_config.GITHUB_REPOSITORY}/branches/{test_config.ANNOTATIONS_DATA_BRANCH}' - )(json={'protected': False, 'name': test_config.ANNOTATIONS_DATA_BRANCH}) - session.register( - 'GET', - f'/repos/{test_config.GITHUB_REPOSITORY}/contents/{test_config.GITHUB_PR_NUMBER}-annotations.json', - params={'ref': test_config.ANNOTATIONS_DATA_BRANCH}, - )(json={'sha': 'abc'}) - session.register( - 'PUT', - f'/repos/{test_config.GITHUB_REPOSITORY}/contents/{test_config.GITHUB_PR_NUMBER}-annotations.json', - json={ - 'message': COMMIT_MESSAGE, - 'branch': test_config.ANNOTATIONS_DATA_BRANCH, - 'sha': 'abc', - 'committer': {'name': gh.user.name, 'email': gh.user.email}, - 'content': base64.b64encode(json.dumps(annotations, cls=AnnotationEncoder).encode()).decode(), - }, - )(status_code=404) - with pytest.raises(CannotGetBranch): - gh.write_annotations_to_branch(annotations=annotations) - gh_init_user_mock.assert_called_once() - gh_init_pr_number_mock.assert_called_once() - gh_init_pr_diff_mock.assert_called_once() - - session.register( - 'GET', f'/repos/{test_config.GITHUB_REPOSITORY}/branches/{test_config.ANNOTATIONS_DATA_BRANCH}' - )(json={'protected': False, 'name': test_config.ANNOTATIONS_DATA_BRANCH}) - session.register( - 'GET', - f'/repos/{test_config.GITHUB_REPOSITORY}/contents/{test_config.GITHUB_PR_NUMBER}-annotations.json', - params={'ref': test_config.ANNOTATIONS_DATA_BRANCH}, - )(json={'sha': 'abc'}) - session.register( - 'PUT', - f'/repos/{test_config.GITHUB_REPOSITORY}/contents/{test_config.GITHUB_PR_NUMBER}-annotations.json', - json={ - 'message': COMMIT_MESSAGE, - 'branch': test_config.ANNOTATIONS_DATA_BRANCH, - 'sha': 'abc', - 'committer': {'name': gh.user.name, 'email': gh.user.email}, - 'content': base64.b64encode(json.dumps(annotations, cls=AnnotationEncoder).encode()).decode(), - }, - )(status_code=403) - with pytest.raises(CannotGetBranch): - gh.write_annotations_to_branch(annotations=annotations) - gh_init_user_mock.assert_called_once() - gh_init_pr_number_mock.assert_called_once() - gh_init_pr_diff_mock.assert_called_once() - - session.register( - 'GET', f'/repos/{test_config.GITHUB_REPOSITORY}/branches/{test_config.ANNOTATIONS_DATA_BRANCH}' - )(json={'protected': False, 'name': test_config.ANNOTATIONS_DATA_BRANCH}) - session.register( - 'GET', - f'/repos/{test_config.GITHUB_REPOSITORY}/contents/{test_config.GITHUB_PR_NUMBER}-annotations.json', - params={'ref': test_config.ANNOTATIONS_DATA_BRANCH}, - )(json={'sha': 'abc'}) - session.register( - 'PUT', - f'/repos/{test_config.GITHUB_REPOSITORY}/contents/{test_config.GITHUB_PR_NUMBER}-annotations.json', - json={ - 'message': COMMIT_MESSAGE, - 'branch': test_config.ANNOTATIONS_DATA_BRANCH, - 'sha': 'abc', - 'committer': {'name': gh.user.name, 'email': gh.user.email}, - 'content': base64.b64encode(json.dumps(annotations, cls=AnnotationEncoder).encode()).decode(), - }, - )(status_code=409) - with pytest.raises(CannotGetBranch): - gh.write_annotations_to_branch(annotations=annotations) - gh_init_user_mock.assert_called_once() - gh_init_pr_number_mock.assert_called_once() - gh_init_pr_diff_mock.assert_called_once() - - session.register( - 'GET', f'/repos/{test_config.GITHUB_REPOSITORY}/branches/{test_config.ANNOTATIONS_DATA_BRANCH}' - )(json={'protected': False, 'name': test_config.ANNOTATIONS_DATA_BRANCH}) - session.register( - 'GET', - f'/repos/{test_config.GITHUB_REPOSITORY}/contents/{test_config.GITHUB_PR_NUMBER}-annotations.json', - params={'ref': test_config.ANNOTATIONS_DATA_BRANCH}, - )(json={'sha': 'abc'}) - session.register( - 'PUT', - f'/repos/{test_config.GITHUB_REPOSITORY}/contents/{test_config.GITHUB_PR_NUMBER}-annotations.json', - json={ - 'message': COMMIT_MESSAGE, - 'branch': test_config.ANNOTATIONS_DATA_BRANCH, - 'sha': 'abc', - 'committer': {'name': gh.user.name, 'email': gh.user.email}, - 'content': base64.b64encode(json.dumps(annotations, cls=AnnotationEncoder).encode()).decode(), - }, - )(status_code=422) - with pytest.raises(CannotGetBranch): - gh.write_annotations_to_branch(annotations=annotations) - gh_init_user_mock.assert_called_once() - gh_init_pr_number_mock.assert_called_once() - gh_init_pr_diff_mock.assert_called_once() - class TestGithubDiffParser: @pytest.mark.parametrize( diff --git a/tests/test_groups.py b/tests/test_groups.py index c678f01..52bad5e 100644 --- a/tests/test_groups.py +++ b/tests/test_groups.py @@ -1,9 +1,8 @@ -import json import pathlib import pytest -from codecov.groups import Annotation, AnnotationEncoder, Group, create_missing_coverage_annotations +from codecov.groups import Annotation, Group, create_missing_coverage_annotations def test_annotation_str(): @@ -40,69 +39,6 @@ def test_annotation_to_dict(): assert annotation.to_dict() == expected_dict -def test_annotation_encode(): - file = pathlib.Path('/path/to/file.py') - annotation = Annotation( - file=file, - line_start=10, - line_end=15, - title='Error', - message_type='ERROR', - message='Something went wrong', - ) - assert isinstance(Annotation.encode([annotation]), str) - - -def test_annotation_encoder_annotation(): - encoder = AnnotationEncoder() - annotation = Annotation( - file='/path/to/file.py', - line_start=10, - line_end=15, - title='Error', - message_type='ERROR', - message='Something went wrong', - ) - expected_dict = { - 'file': '/path/to/file.py', - 'line_start': 10, - 'line_end': 15, - 'title': 'Error', - 'message_type': 'ERROR', - 'message': 'Something went wrong', - } - result = encoder.default(annotation) - assert result == expected_dict - - -def test_annotation_encoder_json(): - annotation = Annotation( - file=pathlib.Path('/path/to/file.py'), - line_start=10, - line_end=15, - title='Error', - message_type='ERROR', - message='Something went wrong', - ) - expected_json = '{"file": "/path/to/file.py", "line_start": 10, "line_end": 15, "title": "Error", "message_type": "ERROR", "message": "Something went wrong"}' - result = json.dumps(annotation, cls=AnnotationEncoder) - assert result == expected_json - - -def test_non_annotation_encoder(): - sample = { - 'file': 'test_file', - 'line_start': 1, - 'line_end': 2, - 'title': 'Test Annotation', - 'message_type': 'warning', - 'message': 'This is a test annotation.', - } - - with pytest.raises(TypeError): - AnnotationEncoder().default(sample) - - @pytest.mark.parametrize( 'annotation_type, annotations, expected_annotations', [ diff --git a/tests/test_main.py b/tests/test_main.py index cbb4657..a0dac9c 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -1,10 +1,9 @@ -import json import pathlib -import tempfile from unittest.mock import MagicMock, patch import pytest +from codecov import template from codecov.coverage.pytest import PytestCoverageHandler from codecov.exceptions import ConfigurationException, CoreProcessingException, MissingMarker, TemplateException from codecov.main import Main @@ -29,7 +28,6 @@ def test_init(self, test_config, gh): assert main.github.client.token == test_config.GITHUB_TOKEN assert main.github.repository == test_config.GITHUB_REPOSITORY assert main.github.pr_number == test_config.GITHUB_PR_NUMBER - assert main.github.annotations_data_branch == test_config.ANNOTATIONS_DATA_BRANCH assert isinstance(main.coverage_module, PytestCoverageHandler) def test_process_coverage(self, test_config, gh, coverage_obj, diff_coverage_obj): @@ -73,19 +71,8 @@ def test_process_coverage_branch_coverage(self, test_config, gh, coverage_obj, d assert main.coverage == coverage_obj assert main.diff_coverage == diff_coverage_obj - def test_render_comment_markdown_skip_coverage(self, test_config, gh, coverage_obj, diff_coverage_obj): - with patch.object(Main, '_init_config', return_value=test_config): - test_config.SKIP_COVERAGE = True - test_config.ANNOTATE_MISSING_LINES = True - with patch.object(Main, '_init_github', return_value=gh): - main = Main() - main.coverage = coverage_obj - main.diff_coverage = diff_coverage_obj - main._render_comment_markdown() - assert main.comment == '' - @patch('codecov.main.template.get_comment_markdown') - def test_render_comment_markdown( + def test_create_comment( self, get_comment_markdown_mock: MagicMock, test_config, @@ -100,7 +87,7 @@ def test_render_comment_markdown( main = Main() main.coverage = coverage_obj main.diff_coverage = diff_coverage_obj - main._render_comment_markdown() + main._create_comment() get_comment_markdown_mock.side_effect = TemplateException with patch.object(Main, '_init_config', return_value=test_config): @@ -109,29 +96,30 @@ def test_render_comment_markdown( main = Main() main.coverage = coverage_obj main.diff_coverage = diff_coverage_obj - main._render_comment_markdown() + main._create_comment() - get_comment_markdown_mock.reset_mock(side_effect=True) - get_comment_markdown_mock.return_value = 'sample comment' + get_comment_markdown_mock.reset_mock() + get_comment_markdown_mock.return_value = '' with patch.object(Main, '_init_config', return_value=test_config): with patch.object(Main, '_init_github', return_value=gh): main = Main() main.coverage = coverage_obj main.diff_coverage = diff_coverage_obj - main._render_comment_markdown() - assert main.comment == 'sample comment' + with pytest.raises(CoreProcessingException): + main._create_comment() - def test_create_comment(self, test_config, gh): + get_comment_markdown_mock.reset_mock(side_effect=True) + get_comment_markdown_mock.return_value = 'sample comment' with patch.object(Main, '_init_config', return_value=test_config): with patch.object(Main, '_init_github', return_value=gh): main = Main() - main.comment = '' - with pytest.raises(CoreProcessingException): - main._create_comment() - - main.comment = 'sample comment' - assert main._create_comment() is None - gh.post_comment.assert_called_once_with(contents='sample comment', marker=main.marker) + main.coverage = coverage_obj + main.diff_coverage = diff_coverage_obj + main._create_comment() + gh.post_comment.assert_called_once_with( + contents='sample comment', + marker=template.MARKER, + ) @patch('codecov.main.groups.create_missing_coverage_annotations') def test_generate_annotations_empty( @@ -184,74 +172,16 @@ def test_generate_annotations(self, test_config, gh, coverage_obj, diff_coverage main.diff_coverage = diff_coverage_obj assert main._generate_annotations() is None - @patch('pathlib.Path.open') - def test_generate_annotations_write_to_file( - self, - mock_open: MagicMock, - test_config, - gh, - coverage_obj, - diff_coverage_obj, - coverage_json, - ): - mock_open.return_value.__enter__.return_value.read.return_value = json.dumps(coverage_json) - with patch.object(Main, '_init_config', return_value=test_config): - with patch.object(Main, '_init_github', return_value=gh): - main = Main() - main.config.ANNOTATE_MISSING_LINES = True - main.config.ANNOTATIONS_OUTPUT_PATH = pathlib.Path(tempfile.mkdtemp()) - main.coverage = coverage_obj - main.diff_coverage = diff_coverage_obj - assert main._generate_annotations() is None - mock_open.assert_called_once() - - mock_open.reset_mock() - with patch.object(Main, '_init_config', return_value=test_config): - with patch.object(Main, '_init_github', return_value=gh): - main = Main() - main.config.BRANCH_COVERAGE = True - main.config.ANNOTATE_MISSING_LINES = True - main.config.ANNOTATIONS_OUTPUT_PATH = pathlib.Path(tempfile.mkdtemp()) - main.coverage = coverage_obj - main.diff_coverage = diff_coverage_obj - assert main._generate_annotations() is None - mock_open.assert_called_once() - - def test_generate_annotations_write_to_branch(self, test_config, gh, coverage_obj, diff_coverage_obj): - with patch.object(Main, '_init_config', return_value=test_config): - with patch.object(Main, '_init_github', return_value=gh): - main = Main() - main.config.ANNOTATE_MISSING_LINES = True - main.config.ANNOTATIONS_DATA_BRANCH = 'sample-branch' - main.coverage = coverage_obj - main.diff_coverage = diff_coverage_obj - assert main._generate_annotations() is None - gh.write_annotations_to_branch.assert_called_once() - - gh.write_annotations_to_branch.reset_mock() - with patch.object(Main, '_init_config', return_value=test_config): - with patch.object(Main, '_init_github', return_value=gh): - main = Main() - main.config.BRANCH_COVERAGE = True - main.config.ANNOTATE_MISSING_LINES = True - main.config.ANNOTATIONS_DATA_BRANCH = 'sample-branch' - main.coverage = coverage_obj - main.diff_coverage = diff_coverage_obj - assert main._generate_annotations() is None - gh.write_annotations_to_branch.assert_called_once() - def test_run(self, test_config, gh): with patch.object(Main, '_init_config', return_value=test_config): with patch.object(Main, '_init_github', return_value=gh): main = Main() main._process_coverage = MagicMock() - main._render_comment_markdown = MagicMock() main._create_comment = MagicMock() main._generate_annotations = MagicMock() assert main.run() is None main._process_coverage.assert_called_once() - main._render_comment_markdown.assert_called_once() main._create_comment.assert_called_once() main._generate_annotations.assert_called_once()