From 8490f88227aff85aacf5edd87f65fded75f7ba65 Mon Sep 17 00:00:00 2001 From: Arthur Meyre Date: Mon, 11 Oct 2021 16:58:24 +0200 Subject: [PATCH] chore: change coverage to have global infos - have a small hack to dump pytest-cov report --- .github/workflows/continuous-integration.yaml | 2 +- .gitignore | 1 + Makefile | 3 +- script/actions_utils/coverage.sh | 19 +---- .../actions_utils/coverage_report_format.py | 74 +++++++++++++------ tests/conftest.py | 30 ++++++++ 6 files changed, 88 insertions(+), 41 deletions(-) diff --git a/.github/workflows/continuous-integration.yaml b/.github/workflows/continuous-integration.yaml index 210a5a7d3..3526e6cfe 100644 --- a/.github/workflows/continuous-integration.yaml +++ b/.github/workflows/continuous-integration.yaml @@ -287,7 +287,7 @@ jobs: id: coverage if: ${{ always() && steps.pytest.outcome != 'skipped' && !cancelled() }} run: | - ./script/actions_utils/coverage.sh ${{ github.base_ref }} + ./script/actions_utils/coverage.sh global-coverage-infos.json - name: Archive test coverage uses: actions/upload-artifact@27121b0bdffd731efa15d66772be8dc71245d074 if: ${{ steps.coverage.outcome != 'skipped' && !cancelled() }} diff --git a/.gitignore b/.gitignore index 679f9b1ff..5e34e4312 100644 --- a/.gitignore +++ b/.gitignore @@ -52,6 +52,7 @@ diff-coverage.txt *.py,cover .hypothesis/ .pytest_cache/ +global-coverage-infos.json # Translations *.mo diff --git a/Makefile b/Makefile index 12b7b600b..8b9719eda 100644 --- a/Makefile +++ b/Makefile @@ -78,8 +78,9 @@ pcc_internal: $(PCC_DEPS) pytest: poetry run pytest -svv \ + --global-coverage-infos-json global-coverage-infos.json \ --cov=$(SRC_DIR) --cov-fail-under=100 \ - --cov-report=term-missing:skip-covered --cov-report=xml tests/ + --cov-report=term-missing:skip-covered tests/ .PHONY: pytest # Not a huge fan of ignoring missing imports, but some packages do not have typing stubs diff --git a/script/actions_utils/coverage.sh b/script/actions_utils/coverage.sh index 90f400e2f..e8ecc73c3 100755 --- a/script/actions_utils/coverage.sh +++ b/script/actions_utils/coverage.sh @@ -5,21 +5,8 @@ set +e CURR_DIR=$(dirname "$0") -# Run diff-coverage -if [[ "$1" == "" ]]; then - export BB="origin/main" -else - export BB="origin/$1" -fi -make coverage | tee diff-coverage.txt - -# Get exit code without closing the script -TEST_EXIT_CODE="$?" - # Format diff-coverage.txt for PR comment poetry run python "$CURR_DIR"/coverage_report_format.py \ ---diff-cover-exit-code "$TEST_EXIT_CODE" \ ---diff-cover-output diff-coverage.txt - -# Set exit code to the diff coverage check -exit "$TEST_EXIT_CODE" +global-coverage \ +--global-coverage-json-file "$1" \ +--global-coverage-output-file diff-coverage.txt diff --git a/script/actions_utils/coverage_report_format.py b/script/actions_utils/coverage_report_format.py index b27f0149f..bfc4d09f6 100755 --- a/script/actions_utils/coverage_report_format.py +++ b/script/actions_utils/coverage_report_format.py @@ -2,21 +2,14 @@ """Helper script for github actions""" import argparse -import traceback +import json from pathlib import Path -def main(args): - """Entry point""" - diff_cover_file_path = Path(args.diff_cover_output).resolve().absolute() - - diff_cover_content = None - - with open(diff_cover_file_path, "r", encoding="utf-8") as f: - diff_cover_content = f.readlines() - - with open(diff_cover_file_path, "w", encoding="utf-8") as f: - if args.diff_cover_exit_code == 0: +def write_coverage_file(coverage_file_path: Path, exit_code: int, coverage_content): + """Write the formatted coverage to file.""" + with open(coverage_file_path, "w", encoding="utf-8") as f: + if exit_code == 0: f.write("## Coverage passed ✅\n\n") else: f.write("## Coverage failed ❌\n\n") @@ -25,24 +18,59 @@ def main(args): f.write("
Coverage details\n

\n\n") f.write("```\n") - f.writelines(diff_cover_content) + f.writelines(coverage_content) # Close collapsible section f.write("```\n\n") f.write("

\n
\n\n") +def diff_coverage(args): + """diff-coverage entry point.""" + diff_cover_file_path = Path(args.diff_cover_output).resolve() + diff_cover_content = None + + with open(diff_cover_file_path, "r", encoding="utf-8") as f: + diff_cover_content = f.readlines() + + write_coverage_file(diff_cover_file_path, args.diff_cover_exit_code, diff_cover_content) + + +def global_coverage(args): + """global-coverage entry point.""" + global_coverage_json_path = Path(args.global_coverage_json_file).resolve() + global_coverage_infos = None + with open(global_coverage_json_path, "r", encoding="utf-8") as f: + global_coverage_infos = json.load(f) + + exit_code = global_coverage_infos["exit_code"] + coverage_content = global_coverage_infos["content"] + global_coverage_output_file_path = Path(args.global_coverage_output_file).resolve() + write_coverage_file(global_coverage_output_file_path, exit_code, coverage_content) + + +def main(args): + """Entry point""" + args.entry_point(args) + + if __name__ == "__main__": - parser = argparse.ArgumentParser(allow_abbrev=False) + main_parser = argparse.ArgumentParser(allow_abbrev=False) - parser.add_argument("--diff-cover-exit-code", type=int, required=True) - parser.add_argument("--diff-cover-output", type=str, required=True) + sub_parsers = main_parser.add_subparsers(dest="sub-command", required=True) - cli_args = parser.parse_args() + parser_diff_coverage = sub_parsers.add_parser("diff-coverage") - # pylint: disable=broad-except - try: - main(cli_args) - except Exception: - traceback.print_exc() - # pylint: enable=broad-except + parser_diff_coverage.add_argument("--diff-cover-exit-code", type=int, required=True) + parser_diff_coverage.add_argument("--diff-cover-output", type=str, required=True) + parser_diff_coverage.set_defaults(entry_point=diff_coverage) + + parser_global_coverage = sub_parsers.add_parser("global-coverage") + + parser_global_coverage.add_argument("--global-coverage-output-file", type=str, required=True) + parser_global_coverage.add_argument("--global-coverage-json-file", type=str, required=True) + parser_global_coverage.set_defaults(entry_point=global_coverage) + + cli_args = main_parser.parse_args() + + main(cli_args) diff --git a/tests/conftest.py b/tests/conftest.py index c5d45b98b..5b41347e4 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,5 +1,7 @@ """PyTest configuration file""" +import json import operator +from pathlib import Path from typing import Callable, Dict, Type import networkx as nx @@ -19,6 +21,34 @@ from concrete.common.representation.intermediate import ( ) +def pytest_addoption(parser): + """Options for pytest""" + + parser.addoption( + "--global-coverage-infos-json", + type=str, + help="To dump pytest-cov term report to a text file.", + ) + + +def pytest_sessionfinish(session: pytest.Session, exitstatus): + """Pytest callback when testing ends.""" + # Hacked together from the source code, they don't have an option to export to file and it's too + # much work to get a PR in for such a little thing + # https://github.com/pytest-dev/pytest-cov/blob/ + # ec344d8adf2d78238d8f07cb20ed2463d7536970/src/pytest_cov/plugin.py#L329 + if session.config.pluginmanager.hasplugin("_cov"): + global_coverage_file = session.config.getoption( + "--global-coverage-infos-json", default=None + ) + if global_coverage_file is not None: + cov_plugin = session.config.pluginmanager.getplugin("_cov") + coverage_txt = cov_plugin.cov_report.getvalue() + global_coverage_file_path = Path(global_coverage_file).resolve() + with open(global_coverage_file_path, "w", encoding="utf-8") as f: + json.dump({"exit_code": exitstatus, "content": coverage_txt}, f) + + def _is_equivalent_to_binary_commutative(lhs: IntermediateNode, rhs: object) -> bool: """is_equivalent_to for a binary and commutative operation.""" return (