diff options
| author | Craig Jennings <c@cjennings.net> | 2026-05-03 17:20:54 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-05-03 17:20:54 -0500 |
| commit | 1d9d252e8b9e1385337cd0af087a7007f8e62da8 (patch) | |
| tree | 4c774bbed6db0b0167e0235a39d5aeaab021ce9c /tests/test-dev-fkeys--f6-test-runner-cmd-for.el | |
| parent | 2c94acd52cc92dc4ebefd999dbca771367cc3090 (diff) | |
| download | dotemacs-1d9d252e8b9e1385337cd0af087a7007f8e62da8.tar.gz dotemacs-1d9d252e8b9e1385337cd0af087a7007f8e62da8.zip | |
feat(dev-fkeys): add F6 test runner menu (Phase 2a)
I extended `dev-fkeys.el` with the F6 dispatcher half of the spec. F6 prompts via `completing-read` between two candidates: "All tests" delegates to `projectile-test-project`, and "Current file's tests" detects the buffer's language by extension, derives the runner command, and pipes through `compile' from the projectile root. C-F6 is the fast path straight to "Current file's tests".
Per-language coverage:
- Elisp source files map to `make test-name TEST=^test-<stem>-`. Elisp test files run with `make test-file FILE=<rel-path>` so a per-helper file like `test-foo--bar.el' runs only its own tests.
- Python source files map to `pytest tests/test_<stem>.py'. Python test files run with `pytest <rel-path>'.
- Go runs the package containing the file: `go test ./<rel-dir>'. Source and test files use the same command since Go test scope is per-package. Limit: this runs every `_test.go' in the package, not just the buffer's file. Phase 2b can refine via test-name discovery.
- TypeScript and JavaScript are detected but punted for v1. The runner-command builder returns nil and the orchestrator signals a user-error rather than guessing.
The F6 binding moved from the Phase 1 stopgap (`projectile-test-project') to `cj/f6-test-runner'. C-F6 is newly bound to `cj/f6-current-file-tests'. M-F6 stays unbound, reserved for Phase 2b's "Run a test..." menu entry.
TDD: 68 new tests across 7 files. Production code split into small testable internals (`cj/--f6-language-detect', `cj/--f6-buffer-is-test-file-p', `cj/--f6-source-stem', `cj/--f6-test-runner-cmd-for', `cj/--f6-current-file-tests-impl') plus two thin interactive wrappers. Smoke tests confirm bindings register on load.
I also updated the module commentary with the Phase 2b plan, the capture-then-filter approach for tree-sitter discovery, and a pointer to Emacs bug #79687. The bug is the predicate-syntax mismatch that breaks `:match' / `:equal' / `:pred' queries on Emacs 30.2 with libtree-sitter 0.26. The fix lives on Emacs master (commit b0143530), targets Emacs 31, and has not been backported to the emacs-30 branch as of today. Phase 2b will use queries without predicates and filter results in Elisp, sidestepping the issue. Mike Olson's `treesit-predicate-rewrite.el' applies the same idea to font-lock if you want it before Phase 2b lands.
Diffstat (limited to 'tests/test-dev-fkeys--f6-test-runner-cmd-for.el')
| -rw-r--r-- | tests/test-dev-fkeys--f6-test-runner-cmd-for.el | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/tests/test-dev-fkeys--f6-test-runner-cmd-for.el b/tests/test-dev-fkeys--f6-test-runner-cmd-for.el new file mode 100644 index 00000000..d9f8f464 --- /dev/null +++ b/tests/test-dev-fkeys--f6-test-runner-cmd-for.el @@ -0,0 +1,112 @@ +;;; test-dev-fkeys--f6-test-runner-cmd-for.el --- Tests for cj/--f6-test-runner-cmd-for -*- lexical-binding: t -*- + +;;; Commentary: +;; Tests for the per-language test-runner-command builder. +;; +;; Inputs are five primitives the orchestrator pre-computes: +;; +;; LANGUAGE symbol from `cj/--f6-language-detect' +;; IS-TEST-FILE boolean from `cj/--f6-buffer-is-test-file-p' +;; REL-PATH file path relative to project root +;; STEM source module stem from `cj/--f6-source-stem' +;; REL-DIR file's directory relative to project root +;; +;; Returns a shell command string to pipe through `compile', or nil for +;; languages we don't have a runner for. The TS / JS handlers are punted +;; for v1 — they return nil. + +;;; Code: + +(require 'ert) +(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory)) +(require 'dev-fkeys) + +;;; Normal Cases — Elisp + +(ert-deftest test-dev-fkeys-f6-cmd-for-elisp-test-file () + "Normal: an elisp test file runs via `make test-file FILE=<path>'." + (should (string= + (cj/--f6-test-runner-cmd-for + 'elisp t "tests/test-foo.el" "foo" "tests") + "make test-file FILE=tests/test-foo.el"))) + +(ert-deftest test-dev-fkeys-f6-cmd-for-elisp-source-file () + "Normal: an elisp source file runs via `make test-name TEST=^test-<stem>-'. +The trailing hyphen anchors the regex so test names from a different +module that happen to share a prefix don't get pulled in." + (should (string= + (cj/--f6-test-runner-cmd-for + 'elisp nil "modules/foo.el" "foo" "modules") + "make test-name TEST=^test-foo-"))) + +;;; Normal Cases — Python + +(ert-deftest test-dev-fkeys-f6-cmd-for-python-test-file () + "Normal: a Python test file runs via `pytest <rel-path>'." + (should (string= + (cj/--f6-test-runner-cmd-for + 'python t "tests/test_foo.py" "foo" "tests") + "pytest tests/test_foo.py"))) + +(ert-deftest test-dev-fkeys-f6-cmd-for-python-source-file () + "Normal: a Python source file runs via `pytest tests/test_<stem>.py'." + (should (string= + (cj/--f6-test-runner-cmd-for + 'python nil "pkg/foo.py" "foo" "pkg") + "pytest tests/test_foo.py"))) + +;;; Normal Cases — Go + +(ert-deftest test-dev-fkeys-f6-cmd-for-go-test-file () + "Normal: a Go test file runs the package via `go test ./<rel-dir>'." + (should (string= + (cj/--f6-test-runner-cmd-for + 'go t "pkg/foo_test.go" "foo" "pkg") + "go test ./pkg"))) + +(ert-deftest test-dev-fkeys-f6-cmd-for-go-source-file () + "Normal: a Go source file runs the same package via `go test ./<rel-dir>'. +Go test scope is per-package; running the source's package picks up its +test files." + (should (string= + (cj/--f6-test-runner-cmd-for + 'go nil "pkg/foo.go" "foo" "pkg") + "go test ./pkg"))) + +;;; Boundary Cases + +(ert-deftest test-dev-fkeys-f6-cmd-for-elisp-test-file-with-double-dash () + "Boundary: a per-helper test file runs only that file, not the whole +test-name prefix. `make test-file FILE=...' is precise; `test-name' +would over-match." + (should (string= + (cj/--f6-test-runner-cmd-for + 'elisp t "tests/test-foo--bar.el" "foo" "tests") + "make test-file FILE=tests/test-foo--bar.el"))) + +(ert-deftest test-dev-fkeys-f6-cmd-for-go-source-at-root () + "Boundary: a Go source file at project root runs `go test ./'." + (should (string= + (cj/--f6-test-runner-cmd-for + 'go nil "main.go" "main" "") + "go test ./"))) + +;;; Error Cases + +(ert-deftest test-dev-fkeys-f6-cmd-for-typescript-returns-nil () + "Error: TypeScript is punted for v1 and returns nil." + (should (null (cj/--f6-test-runner-cmd-for + 'typescript t "src/foo.test.ts" "foo" "src")))) + +(ert-deftest test-dev-fkeys-f6-cmd-for-javascript-returns-nil () + "Error: JavaScript is punted for v1 and returns nil." + (should (null (cj/--f6-test-runner-cmd-for + 'javascript t "src/foo.test.js" "foo" "src")))) + +(ert-deftest test-dev-fkeys-f6-cmd-for-unknown-returns-nil () + "Error: an unknown language returns nil." + (should (null (cj/--f6-test-runner-cmd-for + 'unknown nil "Makefile" "Makefile" "")))) + +(provide 'test-dev-fkeys--f6-test-runner-cmd-for) +;;; test-dev-fkeys--f6-test-runner-cmd-for.el ends here |
