aboutsummaryrefslogtreecommitdiff
path: root/tests/run-coverage-file.el
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-06 10:31:30 -0500
committerCraig Jennings <c@cjennings.net>2026-06-06 10:31:30 -0500
commit95dbb5abdbb746cf5da9f7926740d17205ac8d55 (patch)
tree0e807d43d8f8ce32b3790efc716c433d35ceca3c /tests/run-coverage-file.el
parent6ecd1e9bf1e3d0cdd3861077318541e193ca4532 (diff)
downloadduet-95dbb5abdbb746cf5da9f7926740d17205ac8d55.tar.gz
duet-95dbb5abdbb746cf5da9f7926740d17205ac8d55.zip
build: add Eask, test harness, and dev tooling
I brought the skeleton up to a working package baseline (Phase 0 in the design spec). Eask defines the package and its dev deps. A root Makefile delegates test targets to tests/Makefile and adds compile, coverage, lint, doctor, and clean, matching the layout the other packages use. deps installs both halves DUET needs: the Emacs Lisp deps via eask, and the transport CLIs (rsync, rclone, lftp, unison) via the system package manager, so a contributor's environment is ready before the code that shells out to them. make complexity runs a small homegrown McCabe branch counter (scripts/duet-complexity.el). No off-the-shelf tool measures Emacs Lisp: lizard doesn't support it and codemetrics is an interactive overlay, so DUET owns one. The counting is pure and covered by Normal/Boundary/Error tests. The budget is soft and the target is advisory. The ERT harness (bootstrap, check-deps, per-file undercover coverage) and a smoke test prove the loop works end to end.
Diffstat (limited to 'tests/run-coverage-file.el')
-rw-r--r--tests/run-coverage-file.el50
1 files changed, 50 insertions, 0 deletions
diff --git a/tests/run-coverage-file.el b/tests/run-coverage-file.el
new file mode 100644
index 0000000..550fc90
--- /dev/null
+++ b/tests/run-coverage-file.el
@@ -0,0 +1,50 @@
+;;; run-coverage-file.el --- Undercover setup for per-file coverage runs -*- lexical-binding: t; -*-
+
+;;; Commentary:
+;; Loaded by `make coverage' before each test file runs, BEFORE duet.el is
+;; loaded. Instrumenting must happen first so the subsequent load picks up the
+;; instrumented source.
+;;
+;; Coverage data is merged across per-file invocations into a single simplecov
+;; JSON at .coverage/simplecov.json (under the project root).
+
+;;; Code:
+
+(unless (require 'undercover nil t)
+ (message "")
+ (message "ERROR: undercover not installed.")
+ (message "Run 'make setup' to install development dependencies.")
+ (message "")
+ (kill-emacs 1))
+
+;; Resolve project root from this file's location so undercover patterns and
+;; the report-file path don't depend on default-directory at load time.
+(defvar run-coverage--project-root
+ (file-name-directory
+ (directory-file-name
+ (file-name-directory (or load-file-name buffer-file-name))))
+ "Absolute path to the duet project root.")
+
+;; Force coverage collection in non-CI environments. Must be set after loading
+;; undercover because the library's top-level form
+;; `(setq undercover-force-coverage (getenv "UNDERCOVER_FORCE"))' would
+;; otherwise overwrite the value.
+(setq undercover-force-coverage t)
+
+;; Local runs emit simplecov for whatever local tooling wants it. CI sets
+;; CI=true (GitHub Actions does this automatically), so we emit a coveralls
+;; JSON instead and leave it on disk for the upload action to pick up. The
+;; `undercover' macro splices each configuration list into `(list ,@it)', which
+;; evaluates the elements. Wildcard strings have to stay atoms — using the
+;; `(:files ...)' form lets us evaluate `expand-file-name' to an absolute path.
+(undercover (:files (expand-file-name "duet.el" run-coverage--project-root))
+ (:report-format (if (getenv "CI") 'coveralls 'simplecov))
+ (:report-file (expand-file-name
+ (if (getenv "CI")
+ ".coverage/coveralls.json"
+ ".coverage/simplecov.json")
+ run-coverage--project-root))
+ (:merge-report t)
+ (:send-report nil))
+
+;;; run-coverage-file.el ends here