Hello! I've been trying to do some interactive testing so that I can use testcover to create new tests for `org-agenda-format-item' as Ihor suggested.
I've been quite annoyed at the constant prompts while running the test suite and then when trying to close Emacs so here is a patch to fix that! I've tested this in batch-mode on Emacs 28.2, Emacs 29.4, and Emacs 30.2. I tested it interactively on Emacs 30.2. I've done this using guix and will share my methods in the future as they should be quite reproducible (and maybe good in a CI?). note: "test-org-agenda/time-grid" currently fails interactivly as the value of `org-agenda-time-grid' depends on `(display-graphic-p)' but that's an issue for another day.
>From b3be8b9a552e1a80e01307b41e0e1b002c09b89d Mon Sep 17 00:00:00 2001 From: Morgan Smith <[email protected]> Date: Mon, 11 Aug 2025 13:24:36 -0400 Subject: [PATCH 1/2] * testing/lisp/test-org-agenda.el: Isolate test errors If a test failed, it would not perform the cleanup which would cause all subsequent tests to fail. * testing/lisp/test-org-agenda.el (org-test-agenda-with-agenda): Use unwind-protect to ensure cleanup happens. --- testing/lisp/test-org-agenda.el | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/testing/lisp/test-org-agenda.el b/testing/lisp/test-org-agenda.el index e59461bdb..47425a4e9 100644 --- a/testing/lisp/test-org-agenda.el +++ b/testing/lisp/test-org-agenda.el @@ -46,8 +46,10 @@ org-test-agenda-with-agenda (declare (indent 1)) `(org-test-with-temp-text-in-file ,text (let ((org-agenda-files `(,buffer-file-name))) - ,@body - (org-test-agenda--kill-all-agendas)))) + (unwind-protect + (progn + ,@body) + (org-test-agenda--kill-all-agendas))))) ;; Test the Agenda base-commit: 1afa553ed174c193f026c12c7ac6ea79214f427e -- 2.51.0
>From 87a754612094a3cbfa83803842a25cff9dbb0faa Mon Sep 17 00:00:00 2001 From: Morgan Smith <[email protected]> Date: Thu, 16 Oct 2025 13:40:58 -0400 Subject: [PATCH 2/2] testing: Suppress interactive prompts during testing and on quit Running the tests interactively would give the user multiple prompts asking if they wanted to kill a modified buffer. Then when quitting Emacs, the user would receive prompts asking if they wanted to save some of the temporary test files. * testing/org-test.el (org-test-kill-buffer): New function. (org-test-at-id, org-test-in-example-file, org-test-with-temp-text-in-file, org-test-kill-all-examples): Use new function to kill buffers. * testing/lisp/test-ob-tangle.el (ob-tangle/tangle-to-self, ob-tangle/bibtex): Use `org-test-with-temp-text-in-file' to ensure buffers are killed. * testing/lisp/test-org-agenda.el (test-org-agenda/set-priority): Use `unwind-protect' for test cleanup and kill a buffer to "agenda-file.org". * testing/lisp/test-org-capture.el (test-org-capture/org-capture-expand-olp): Use `org-test-with-temp-text-in-file' to ensure buffers are killed. * testing/lisp/test-org-protocol.el (test-org-protocol/org-protocol-capture-file): Add cleanup for buffers and files. * testing/lisp/test-ox.el (test-org-export/org-export-copy-buffer): Kill buffer. --- testing/lisp/test-ob-tangle.el | 45 +++++++++++++------------------ testing/lisp/test-org-agenda.el | 12 +++++---- testing/lisp/test-org-capture.el | 18 +++++-------- testing/lisp/test-org-protocol.el | 16 ++++++----- testing/lisp/test-ox.el | 3 ++- testing/org-test.el | 24 ++++++++++------- 6 files changed, 58 insertions(+), 60 deletions(-) diff --git a/testing/lisp/test-ob-tangle.el b/testing/lisp/test-ob-tangle.el index cd6876370..0104453cb 100644 --- a/testing/lisp/test-ob-tangle.el +++ b/testing/lisp/test-ob-tangle.el @@ -555,17 +555,14 @@ ob-tangle/strip-tangle (ert-deftest ob-tangle/tangle-to-self () "Do not allow tangling into self." - (let ((file (make-temp-file "org-tangle-" nil ".org"))) - (unwind-protect - (with-current-buffer (find-file-noselect file) - (insert - (format " -#+begin_src elisp :tangle %s + (org-test-with-temp-text-in-file + " +#+begin_src elisp :tangle <point> 2 #+end_src -" file)) - (should-error (org-babel-tangle))) - (delete-file file)))) +" + (insert file) + (should-error (org-babel-tangle)))) (ert-deftest ob-tangle/detangle-false-positive () "Test handling of false positive link during detangle." @@ -717,29 +714,25 @@ ob-tangle/collect-blocks (ert-deftest ob-tangle/bibtex () "Tangle BibTeX into a `.bib' file." - (let ((file (make-temp-file "org-tangle-" nil ".org")) - (bib "@Misc{example, + (let ((bib "@Misc{example, author = {Richard Stallman and {contributors}}, title = {{GNU} {Emacs}}, publisher = {Free Software Foundation}, url = {https://www.emacs.org/}, }")) - (unwind-protect - (with-current-buffer (find-file-noselect file) - (insert (format "#+begin_src bibtex :tangle yes + (org-test-with-temp-text-in-file + (format "#+begin_src bibtex :tangle yes %s -#+end_src" - bib)) - (org-babel-tangle) - (let ((bib-file - (if (fboundp 'file-name-with-extension) - (file-name-with-extension file "bib") - ;; Emacs <28 - (concat (file-name-sans-extension file) "." "bib")))) - (should (file-exists-p bib-file)) - (should (string= (string-trim (org-file-contents bib-file)) - bib)))) - (delete-file file)))) +#+end_src" bib) + (org-babel-tangle) + (let ((bib-file + (if (fboundp 'file-name-with-extension) + (file-name-with-extension file "bib") + ;; Emacs <28 + (concat (file-name-sans-extension file) "." "bib")))) + (should (file-exists-p bib-file)) + (should (string= (string-trim (org-file-contents bib-file)) + bib)))))) ;; See https://list.orgmode.org/87msfxd81c.fsf@localhost/T/#t (ert-deftest ob-tangle/tangle-from-capture-buffer () diff --git a/testing/lisp/test-org-agenda.el b/testing/lisp/test-org-agenda.el index 47425a4e9..1abc53028 100644 --- a/testing/lisp/test-org-agenda.el +++ b/testing/lisp/test-org-agenda.el @@ -378,11 +378,13 @@ test-org-agenda/set-priority ;; `org-today' or not. (org-agenda-list nil "<2017-07-19 Wed>") (set-buffer org-agenda-buffer-name) - (should - (progn (goto-line 3) - (org-agenda-priority ?B) - (looking-at-p " *agenda-file:Scheduled: *\\[#B\\] test agenda")))) - (org-test-agenda--kill-all-agendas)) + (unwind-protect + (should + (progn (goto-line 3) + (org-agenda-priority ?B) + (looking-at-p " *agenda-file:Scheduled: *\\[#B\\] test agenda"))) + (org-test-agenda--kill-all-agendas) + (org-test-kill-buffer "agenda-file.org")))) (ert-deftest test-org-agenda/sticky-agenda-name () "Agenda buffer name after having created one sticky agenda buffer." diff --git a/testing/lisp/test-org-capture.el b/testing/lisp/test-org-capture.el index 494fee4cf..1a0496046 100644 --- a/testing/lisp/test-org-capture.el +++ b/testing/lisp/test-org-capture.el @@ -1089,28 +1089,22 @@ test-org-capture/org-capture-expand-olp (should (equal '("A" "B" "C") - (let ((file (make-temp-file "org-test"))) - (unwind-protect - (org-capture-expand-olp file "A" "B" "C") - (delete-file file))))) + (org-test-with-temp-text-in-file "" + (org-capture-expand-olp file "A" "B" "C")))) ;; The current buffer during the funcall of the lambda is the temporary ;; test file. (should - (let ((file (make-temp-file "org-test"))) + (org-test-with-temp-text-in-file "" (equal file - (unwind-protect - (org-capture-expand-olp file (lambda () (buffer-file-name))) - (delete-file file))))) + (org-capture-expand-olp file (lambda () (buffer-file-name)))))) ;; `org-capture-expand-olp' rejects outline path that is not ;; inlined. (should-error (equal '("A" "B" "C") - (let ((file (make-temp-file "org-test"))) - (unwind-protect - (org-capture-expand-olp file '("A" "B" "C")) - (delete-file file)))))) + (org-test-with-temp-text-in-file "" + (org-capture-expand-olp file '("A" "B" "C")))))) (provide 'test-org-capture) ;;; test-org-capture.el ends here diff --git a/testing/lisp/test-org-protocol.el b/testing/lisp/test-org-protocol.el index 6429432a3..d31940d3e 100644 --- a/testing/lisp/test-org-protocol.el +++ b/testing/lisp/test-org-protocol.el @@ -164,12 +164,16 @@ test-org-protocol/org-protocol-capture-file (temp-file-name (make-temp-file "org-protocol-test")) (org-capture-templates `(("t" "Test" plain (file ,temp-file-name) "%a\n%i\n" :kill-buffer t)))) - (let ((uri "/org-protocol:/capture:/t/file%3A%2F%2F%2Fetc%2Fmailcap/Triple%20Slash/Body")) - (should (null (org-protocol-check-filename-for-protocol uri (list uri) nil))) - (should (string= (buffer-string) "[[file:///etc/mailcap][Triple Slash]]\nBody"))) - (let ((uri "/org-protocol:/capture?template=t&url=file%3A%2F%2F%2Fetc%2Fmailcap&title=Triple%20Slash&body=Body")) - (should (null (org-protocol-check-filename-for-protocol uri (list uri) nil))) - (should (string= (buffer-string) "[[file:///etc/mailcap][Triple Slash]]\nBody"))))) + (unwind-protect + (progn + (let ((uri "/org-protocol:/capture:/t/file%3A%2F%2F%2Fetc%2Fmailcap/Triple%20Slash/Body")) + (should (null (org-protocol-check-filename-for-protocol uri (list uri) nil))) + (should (string= (buffer-string) "[[file:///etc/mailcap][Triple Slash]]\nBody"))) + (let ((uri "/org-protocol:/capture?template=t&url=file%3A%2F%2F%2Fetc%2Fmailcap&title=Triple%20Slash&body=Body")) + (should (null (org-protocol-check-filename-for-protocol uri (list uri) nil))) + (should (string= (buffer-string) "[[file:///etc/mailcap][Triple Slash]]\nBody")))) + (org-test-kill-buffer (get-file-buffer temp-file-name)) + (delete-file temp-file-name)))) (ert-deftest test-org-protocol/org-protocol-open-source () "Test org-protocol://open-source links." diff --git a/testing/lisp/test-ox.el b/testing/lisp/test-ox.el index 279642d94..ddf37a5f6 100644 --- a/testing/lisp/test-ox.el +++ b/testing/lisp/test-ox.el @@ -75,7 +75,8 @@ test-org-export/org-export-copy-buffer "* Heading" (with-temp-buffer (insert-file-contents file) - (buffer-string))))))) + (buffer-string)))) + (org-test-kill-buffer (current-buffer))))) ;; The copy must not show when re-opening the original file. (org-test-with-temp-text-in-file "* Heading" diff --git a/testing/org-test.el b/testing/org-test.el index 46ec56608..a6e14e3a5 100644 --- a/testing/org-test.el +++ b/testing/org-test.el @@ -116,6 +116,15 @@ org-test-compare-with-file If file is not given, search for a file named after the test currently executed.") +(defun org-test-kill-buffer (buffer) + "Kill BUFFER like `kill-buffer' but without user interaction." + (setq buffer (get-buffer buffer)) + (when (and buffer (buffer-live-p buffer)) + (with-current-buffer buffer + ;; Prevent "Buffer *temp* modified; kill anyway?". + (set-buffer-modified-p nil) + (kill-buffer)))) + (defmacro org-test-at-id (id &rest body) "Run body after placing the point in the headline identified by ID." (declare (indent 1) (debug t)) @@ -135,7 +144,7 @@ org-test-at-id (error nil)) (save-restriction ,@body))) (unless (or visited-p (not to-be-removed)) - (kill-buffer to-be-removed))))) + (org-test-kill-buffer to-be-removed))))) (defmacro org-test-in-example-file (file &rest body) "Execute body in the Org example file." @@ -158,8 +167,8 @@ org-test-in-example-file (org-fold-show-all '(blocks))) (error nil)) (setq results (save-restriction ,@body)))) - (unless visited-p - (kill-buffer to-be-removed)) + (unless (or visited-p (not to-be-removed)) + (org-test-kill-buffer to-be-removed)) results)) (defmacro org-test-at-marker (file marker &rest body) @@ -213,12 +222,7 @@ org-test-with-temp-text-in-file (org-mode) (progn ,@body)) (let ((kill-buffer-query-functions nil)) - (when buffer - (set-buffer buffer) - ;; Ignore changes, we're deleting the file in the next step - ;; anyways. - (set-buffer-modified-p nil) - (kill-buffer)) + (org-test-kill-buffer buffer) (delete-file file))))) (defun org-test-table-target-expect (target &optional expect laps &rest tblfm) @@ -451,7 +455,7 @@ org-test-touch-all-examples (defun org-test-kill-all-examples () (while org-test-buffers (let ((b (pop org-test-buffers))) - (when (buffer-live-p b) (kill-buffer b))))) + (org-test-kill-buffer b)))) (defun org-test-update-id-locations () (setq org-id-locations-file -- 2.51.0
