aboutsummaryrefslogtreecommitdiff
path: root/modules/coverage-elisp.el
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-04-22 19:58:00 -0500
committerCraig Jennings <c@cjennings.net>2026-04-22 19:58:00 -0500
commita97266c0e89ef8560824789063512d2613849fc9 (patch)
treeba320ed3d2dfedebade1fa79ece01baaa4750bd3 /modules/coverage-elisp.el
parentecca6c5809aa2945d593baae10308c0dcfe6ec17 (diff)
downloaddotemacs-a97266c0e89ef8560824789063512d2613849fc9.tar.gz
dotemacs-a97266c0e89ef8560824789063512d2613849fc9.zip
feat(coverage): wire make coverage target + simplecov pipeline
Completes the coverage v1 pipeline by adding the Makefile target, the undercover driver script, the exclusion list, and the .gitignore entry. Uses simplecov JSON rather than LCOV as the collection format. The LCOV vs simplecov choice: Undercover's :merge-report t option only supports simplecov. Since the pipeline runs tests per-file (matching test-unit's isolation pattern) and accumulates coverage across runs, merge-report is required. LCOV is better-supported by external coverage viewers, but for a primarily interactive workflow the on-disk format is an internal detail. Other moves in this commit: - Renamed cj/--coverage-parse-lcov to cj/--coverage-parse-simplecov and rewrote its tests for the JSON schema. Same signature, same semantics (file to set of covered lines), different parser. - Renamed the backend protocol's :lcov-path key to :report-path, format-neutral and matching the renamed cj/--coverage-elisp-report-path function. - The coverage target deletes modules/*.elc before running so undercover can instrument the .el sources. Without this, byte-compiled versions shadow the instrumentation and only a handful of pre-loaded modules end up with coverage data. - Excluded tests/test-all-comp-errors.el from make coverage runs. That test byte-compiles every module, which fails under undercover's instrumentation. Excluded only from coverage. Normal make test still runs it. - Updated docs/design/coverage.org to reflect the simplecov pivot with a historical note on why we moved off LCOV. Verified end-to-end: make coverage produces .coverage/simplecov.json with 2717 of 4559 executable lines hit across 44 tracked modules.
Diffstat (limited to 'modules/coverage-elisp.el')
-rw-r--r--modules/coverage-elisp.el24
1 files changed, 13 insertions, 11 deletions
diff --git a/modules/coverage-elisp.el b/modules/coverage-elisp.el
index 63d89906..048c81dd 100644
--- a/modules/coverage-elisp.el
+++ b/modules/coverage-elisp.el
@@ -13,8 +13,10 @@
;; the callback is invoked with the LCOV path; on failure, the buffer
;; stays visible for the user to inspect.
;;
-;; :lcov-path resolves to `<project-root>/.coverage/lcov.info', which
-;; matches the path the Makefile's coverage target writes to.
+;; :report-path resolves to `<project-root>/.coverage/simplecov.json',
+;; which matches the path the Makefile's coverage target writes to.
+;; The simplecov JSON format is used because undercover's `:merge-report'
+;; support only covers simplecov, not LCOV.
;;; Code:
@@ -23,9 +25,9 @@
(use-package undercover
:defer t)
-(defconst cj/--coverage-elisp-lcov-relative-path
- ".coverage/lcov.info"
- "Project-relative path to the LCOV file produced by `make coverage'.")
+(defconst cj/--coverage-elisp-report-relative-path
+ ".coverage/simplecov.json"
+ "Project-relative path to the simplecov JSON produced by `make coverage'.")
(defun cj/--coverage-elisp-project-root (&optional root)
"Return ROOT or fall back to projectile's root or `default-directory'."
@@ -44,14 +46,14 @@ The heuristic needs both (a) a Makefile, Eask, or Cask at ROOT and
(or (file-expand-wildcards (expand-file-name "modules/*.el" root))
(file-expand-wildcards (expand-file-name "*.el" root)))))
-(defun cj/--coverage-elisp-lcov-path (&optional root)
- "Return the absolute path to the LCOV file for ROOT."
- (expand-file-name cj/--coverage-elisp-lcov-relative-path
+(defun cj/--coverage-elisp-report-path (&optional root)
+ "Return the absolute path to the simplecov JSON file for ROOT."
+ (expand-file-name cj/--coverage-elisp-report-relative-path
(cj/--coverage-elisp-project-root root)))
(defun cj/--coverage-elisp-run (callback)
"Run `make coverage' asynchronously.
-CALLBACK is invoked with the LCOV path when the build finishes
+CALLBACK is invoked with the report path when the build finishes
successfully. On failure, no callback is invoked and the compilation
buffer stays visible so the user can read the error."
(let* ((default-directory (cj/--coverage-elisp-project-root))
@@ -61,14 +63,14 @@ buffer stays visible so the user can read the error."
(add-hook 'compilation-finish-functions
(lambda (_buf status)
(when (string-match-p "^finished" status)
- (funcall callback (cj/--coverage-elisp-lcov-path))))
+ (funcall callback (cj/--coverage-elisp-report-path))))
nil t))))
(cj/coverage-register-backend
(list :name 'elisp
:detect #'cj/--coverage-elisp-detect
:run #'cj/--coverage-elisp-run
- :lcov-path #'cj/--coverage-elisp-lcov-path))
+ :report-path #'cj/--coverage-elisp-report-path))
(provide 'coverage-elisp)
;;; coverage-elisp.el ends here