diff options
| author | Craig Jennings <c@cjennings.net> | 2026-05-05 03:10:50 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-05-05 03:10:50 -0500 |
| commit | 77fe06b0c6f01d1d76bdf503c1b12286ac29aa0a (patch) | |
| tree | df8c6ddbd9f48c2bcc18b4e9ef18bb15ea0280f0 /Makefile | |
| parent | 720d6597bf6751ee6d75bb224dd468aa2a78d7ee (diff) | |
| download | org-drill-77fe06b0c6f01d1d76bdf503c1b12286ac29aa0a.tar.gz org-drill-77fe06b0c6f01d1d76bdf503c1b12286ac29aa0a.zip | |
build: add make coverage target via undercover
I want to track test coverage as I work through the upstream issue backlog, so I added an undercover-based flow that mirrors how `make test-unit` already runs each file in its own Cask Emacs process.
The Makefile gets `make coverage` and `make coverage-clean`. A new helper at `tests/run-coverage-file.el` instruments `org-drill.el` before the source is loaded. Undercover merges per-file results into a single simplecov JSON at `.coverage/simplecov.json`. I added `undercover` as a Cask development dep and `.coverage/` to `.gitignore` so the report stays local.
I also renamed `make install` to `make setup`. The old name read like "deploy the package onto my system," but the target only installs Cask deps into the local `.cask/` directory. `setup` is closer to what it actually does, and all the internal `: install` prerequisites move with it.
Baseline at this commit is 10.8% (208/1928 lines on org-drill.el).
Diffstat (limited to 'Makefile')
| -rw-r--r-- | Makefile | 66 |
1 files changed, 58 insertions, 8 deletions
@@ -9,7 +9,7 @@ # make robot - Run basic robot tests # make robot-all - Run all robot tests # make docker-test - Run tests in Docker (multiple Emacs versions) -# make install - Install dependencies via Cask +# make setup - Install dependencies via Cask # make clean - Remove generated files # Emacs binary to use (override with: make EMACS=emacs29 test) @@ -38,9 +38,14 @@ EMACS_BATCH = $(EMACS) --batch --no-site-file --no-site-lisp # Docker configuration DOCKER_TAG=26 -.PHONY: help test test-all test-unit test-integration test-file test-name install build clean clean-elc +# Coverage configuration +COVERAGE_DIR = .coverage +COVERAGE_FILE = $(COVERAGE_DIR)/simplecov.json + +.PHONY: help test test-all test-unit test-integration test-file test-name setup build clean clean-elc .PHONY: robot robot-all robot-basic robot-leitner robot-all-card robot-spanish robot-explainer .PHONY: docker-test test-cp test-git +.PHONY: coverage coverage-clean # Default target help: @@ -58,8 +63,12 @@ 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 "Advanced Targets:" - @echo " make install - Install dependencies via Cask" + @echo " make setup - Install dependencies via Cask" @echo " make build - Build package via Cask" @echo " make docker-test - Run tests in Docker (multiple Emacs versions)" @echo " make clean - Remove generated files" @@ -82,7 +91,7 @@ help: all: robot test-unit # Install dependencies -install: +setup: @if ! command -v $(CASK) >/dev/null 2>&1; then \ echo "[✗] Cask not found. Please install Cask first:"; \ echo " https://github.com/cask/cask"; \ @@ -104,7 +113,7 @@ test: robot test-unit test-all: robot-all test-unit test-integration # Run unit tests only -test-unit: install +test-unit: setup @echo "[i] Running unit tests ($(words $(UNIT_TESTS)) files)..." @failed=0; \ for test in $(UNIT_TESTS); do \ @@ -124,7 +133,7 @@ test-unit: install fi # Run integration tests only -test-integration: install +test-integration: setup @echo "[i] Running integration tests ($(words $(INTEGRATION_TESTS)) files)..." @if [ $(words $(INTEGRATION_TESTS)) -eq 0 ]; then \ echo "[i] No integration tests found"; \ @@ -149,7 +158,7 @@ test-integration: install # Run specific test file # Usage: make test-file FILE=org-drill-test.el -test-file: install +test-file: setup ifndef FILE @echo "[✗] Error: FILE parameter required" @echo "Usage: make test-file FILE=org-drill-test.el" @@ -167,7 +176,7 @@ endif # Run specific test by name/pattern # Usage: make test-name TEST=load-test # make test-name TEST="find-*" -test-name: install +test-name: setup ifndef TEST @echo "[✗] Error: TEST parameter required" @echo "Usage: make test-name TEST=load-test" @@ -184,6 +193,47 @@ endif @echo "[✓] Tests matching '$(TEST)' complete" # +# Coverage (undercover + simplecov JSON) +# +# Each unit-test file runs in its own Emacs process (matching `make +# test-unit'); run-coverage-file.el instruments org-drill.el before the +# source is loaded, and undercover merges per-file results into a single +# simplecov JSON. + +coverage: coverage-clean setup $(COVERAGE_DIR) + @echo "[i] Cleaning .elc files so undercover can instrument source..." + @find . -name "*.elc" -delete + @echo "[i] Running coverage across $(words $(UNIT_TESTS)) unit-test file(s)..." + @echo " (slower than 'make test-unit' — each file runs in its own Emacs)" + @failed=0; \ + for test in $(UNIT_TESTS); do \ + echo " Coverage: $$test..."; \ + $(EMACS_ENV) $(CASK) emacs --batch -q \ + -l ert \ + -l assess \ + -l $(TEST_DIR)/run-coverage-file.el \ + -l org-drill.el \ + -l $$test \ + -f ert-run-tests-batch-and-exit || failed=$$((failed + 1)); \ + done; \ + if [ $$failed -gt 0 ]; then \ + echo "[!] $$failed test file(s) failed during coverage run"; \ + 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) + +# # Robot Tests (Automated UI Tests) # |
