aboutsummaryrefslogtreecommitdiff
path: root/Makefile
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 /Makefile
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 'Makefile')
-rw-r--r--Makefile61
1 files changed, 61 insertions, 0 deletions
diff --git a/Makefile b/Makefile
index 1ee30d4a..a7183d85 100644
--- a/Makefile
+++ b/Makefile
@@ -6,6 +6,8 @@
# make test-unit - Run unit tests only
# make test-file FILE=test-foo.el - Run specific test file
# make test-name TEST=test-foo-* - Run tests matching pattern
+# make coverage - Generate simplecov coverage report
+# make coverage-clean - Remove coverage report file
# make validate-parens - Check for unbalanced parentheses
# make validate-modules - Load all modules to verify they compile
# make compile - Byte-compile all modules
@@ -39,6 +41,7 @@ EMACS_TEST = $(EMACS_BATCH) -L $(TEST_DIR) -L $(MODULE_DIR)
# No colors - using plain text symbols instead
.PHONY: help targets test test-all test-unit test-integration test-file test-name \
+ coverage coverage-clean \
validate-parens validate-modules compile lint profile \
clean clean-compiled clean-tests reset
@@ -58,6 +61,10 @@ help:
@echo " make test-file FILE=<filename> - Run specific test file"
@echo " make test-name TEST=<pattern> - Run tests matching pattern"
@echo ""
+ @echo " Coverage:"
+ @echo " make coverage - Generate simplecov JSON at $(COVERAGE_FILE)"
+ @echo " make coverage-clean - Delete the coverage report file"
+ @echo ""
@echo " Validation:"
@echo " make validate-parens - Check for unbalanced parentheses in modules"
@echo " make validate-modules - Load all modules to verify they compile"
@@ -214,6 +221,60 @@ endif
@echo "✓ Tests matching '$(TEST)' complete"
# ============================================================================
+# Coverage Targets
+# ============================================================================
+
+COVERAGE_DIR = .coverage
+COVERAGE_FILE = $(COVERAGE_DIR)/simplecov.json
+
+# Test files that can't coexist with undercover's instrumentation
+# (e.g. test-all-comp-errors byte-compiles modules, which fails on
+# instrumented sources). Excluded from `make coverage' only.
+COVERAGE_EXCLUDE = $(TEST_DIR)/test-all-comp-errors.el
+COVERAGE_TESTS = $(filter-out $(COVERAGE_EXCLUDE),$(UNIT_TESTS))
+
+coverage: coverage-clean $(COVERAGE_DIR)
+ @echo "[i] Deleting modules/*.elc so undercover can instrument sources..."
+ @rm -f $(MODULE_DIR)/*.elc
+ @echo "[i] Running coverage across $(words $(COVERAGE_TESTS)) test files..."
+ @echo " (this is slower than 'make test' — each file runs in its own Emacs)"
+ @echo " excluded from coverage: $(notdir $(COVERAGE_EXCLUDE))"
+ @echo ""
+ @failed=0; \
+ failed_files=""; \
+ for test in $(COVERAGE_TESTS); do \
+ test_name=$$(basename $$test); \
+ printf " Coverage: %-58s " "$$test_name..."; \
+ output=$$($(EMACS_TEST) -l $(TEST_DIR)/run-coverage-file.el -l $$test --eval "(ert-run-tests-batch-and-exit '(not (tag :slow)))" 2>&1); \
+ result=$$?; \
+ if [ $$result -eq 0 ]; then \
+ echo "✓"; \
+ else \
+ echo "✗"; \
+ failed=$$((failed + 1)); \
+ failed_files="$$failed_files $$test_name"; \
+ fi; \
+ done; \
+ echo ""; \
+ if [ $$failed -gt 0 ]; then \
+ echo "[!] $$failed test file(s) failed during coverage run:"; \
+ echo "$$failed_files" | tr ' ' '\n' | grep -v '^$$' | sed 's/^/ /'; \
+ exit 1; \
+ fi
+ @if [ -f $(COVERAGE_FILE) ]; then \
+ echo "✓ Coverage report: $(COVERAGE_FILE) ($$(du -h $(COVERAGE_FILE) | cut -f1))"; \
+ else \
+ echo "[!] No coverage file produced; check that undercover is installed"; \
+ exit 1; \
+ fi
+
+coverage-clean:
+ @rm -f $(COVERAGE_FILE)
+
+$(COVERAGE_DIR):
+ @mkdir -p $(COVERAGE_DIR)
+
+# ============================================================================
# Validation Targets
# ============================================================================