-
Notifications
You must be signed in to change notification settings - Fork 25
ENH: Add generate-lcov-html flag
#258
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| import contextlib | ||
| import copy | ||
| import itertools | ||
| import json | ||
| import os | ||
| import re | ||
|
|
@@ -14,6 +15,8 @@ | |
| from .util import get_commands, get_config | ||
| from .util import run as _run | ||
|
|
||
| LCOV_OUTPUT_FILE = Path("build", "meson-logs", "coveragereport") | ||
|
|
||
|
|
||
| class GcovReportFormat(str, Enum): | ||
| html = "html" | ||
|
|
@@ -231,6 +234,48 @@ def _check_coverage_tool_installation(coverage_type: GcovReportFormat, build_dir | |
| ) | ||
|
|
||
|
|
||
| def _get_coverage_files(): | ||
| cwd = Path.cwd() | ||
| build_dir = Path(cwd, "build") | ||
| return itertools.chain(build_dir.rglob("*.gcda"), build_dir.rglob("*.da")) | ||
|
|
||
|
|
||
| def _gcov_reset_counters(): | ||
| click.secho("Removing previous GCOV .gcda files...", fg="yellow") | ||
| for filename in _get_coverage_files(): | ||
| Path.unlink(filename) | ||
|
|
||
|
|
||
| def _generate_lcov_coverage_html(): | ||
| if next(_get_coverage_files(), None) is None: | ||
| raise click.ClickException( | ||
| "GCOV files missing... Cannot generate coverage reports. " | ||
| "Coverage reports can be generated by `spin test --coverage --gcov`" | ||
| ) | ||
|
|
||
| click.secho( | ||
| "Deleting old HTML coverage report...", | ||
| fg="yellow", | ||
| ) | ||
| shutil.rmtree(LCOV_OUTPUT_FILE, ignore_errors=True) | ||
|
|
||
| click.secho( | ||
| "Generating HTML coverage report...", | ||
| fg="blue", | ||
| ) | ||
| cmd = ["ninja", "coverage-html", "-C", "build"] | ||
| p = _run( | ||
| cmd, | ||
| echo=True, | ||
| output=False, | ||
| ) | ||
| coverage_folder = re.search(r"file://(.*)", p.stdout.decode("utf-8")).group(1) | ||
| click.secho( | ||
| f"Coverage report generated successfully and written to {coverage_folder}", | ||
| fg="green", | ||
| ) | ||
|
|
||
|
|
||
| if sys.platform.startswith("win"): | ||
| DEFAULT_PREFIX = "C:/" | ||
| else: | ||
|
|
@@ -447,6 +492,13 @@ def _get_configured_command(command_name): | |
| default="html", | ||
| help=f"Format of the gcov report. Can be one of {', '.join(e.value for e in GcovReportFormat)}.", | ||
| ) | ||
| @click.option( | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of adding a new flag, what do you think of adding an
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, it makes sense to club it. It would need a bit of rework I have used the enum to denote the coverage format directly. Let me see how we can make it neater and more generic. |
||
| "--generate-lcov-html", | ||
| is_flag=True, | ||
| help="produce HTML for C code coverage information " | ||
| "from a previous run with --gcov. " | ||
| "HTML output goes to `build/meson-logs/coveragereport/`", | ||
| ) | ||
| @build_dir_option | ||
| @click.pass_context | ||
| def test( | ||
|
|
@@ -459,6 +511,7 @@ def test( | |
| coverage=False, | ||
| gcov=None, | ||
| gcov_format=None, | ||
| generate_lcov_html=None, | ||
| build_dir=None, | ||
| ): | ||
| """🔧 Run tests | ||
|
|
@@ -503,6 +556,10 @@ def test( | |
| distname = cfg.get("project.name", None) | ||
| pytest_args = pytest_args or () | ||
|
|
||
| if generate_lcov_html: | ||
| _generate_lcov_coverage_html() | ||
| sys.exit(0) | ||
|
|
||
| # User specified tests without -t flag | ||
| # Rewrite arguments as though they specified using -t and proceed | ||
| if (len(pytest_args) == 1) and (not tests): | ||
|
|
@@ -547,6 +604,7 @@ def test( | |
| "Invoking `build` prior to running tests:", bold=True, fg="bright_green" | ||
| ) | ||
| if gcov is not None: | ||
| _gcov_reset_counters() | ||
| ctx.invoke(build_cmd, build_dir=build_dir, gcov=bool(gcov)) | ||
| else: | ||
| ctx.invoke(build_cmd, build_dir=build_dir) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will depend on the build path the user specifies, so has to be set inside the build fn.