New convenience macros ert-with-temp-(file|directory)

* lisp/emacs-lisp/ert-x.el
(ert-with-temp-file)
(ert-with-temp-directory): New macros.
* test/lisp/emacs-lisp/ert-x-tests.el
(ert-x-tests-with-temp-directory)
ert-x-tests-with-temp-directory/text-signals-error
(ert-x-tests-with-temp-file)
(ert-x-tests-with-temp-file/handle-error)
(ert-x-tests-with-temp-file/prefix-and-suffix-kwarg)
(ert-x-tests-with-temp-file/text-kwarg)
(ert-x-tests-with-temp-file/unknown-kwargs-signals-error): New tests.
This commit is contained in:
Stefan Kangas 2021-11-06 13:50:46 +01:00
parent 1b1d387b96
commit bf2e35c5d2
2 changed files with 118 additions and 0 deletions

View file

@ -386,6 +386,78 @@ A resource file is defined as any file placed in the resource
directory as returned by `ert-resource-directory'."
`(expand-file-name ,file (ert-resource-directory)))
(defvar ert-temp-file-prefix "emacs-test-"
"Suffix used by `ert-with-temp-file' and `ert-with-temp-directory'.")
(defvar ert-temp-file-suffix nil
"Prefix used by `ert-with-temp-file' and `ert-with-temp-directory'.")
(defmacro ert-with-temp-file (name &rest body)
"Bind NAME to the name of a new temporary file and evaluate BODY.
Delete the temporary file after BODY exits normally or
non-locally. NAME will be bound to the file name of the temporary
file.
The following keyword arguments are supported:
:prefix STRING If non-nil, pass STRING to `make-temp-file' as
the PREFIX argument. Otherwise, use the value
of `ert-temp-file-prefix'.
:suffix STRING If non-nil, pass STRING to `make-temp-file' as
the SUFFIX argument. Otherwise, use the value
of `ert-temp-file-suffix'.
:text STRING If non-nil, pass STRING to `make-temp-file' as
the TEXT argument.
See also `ert-with-temp-directory'."
(declare (indent 1) (debug (symbolp body)))
(cl-check-type name symbol)
(let (keyw prefix suffix directory text extra-keywords)
(while (keywordp (setq keyw (car body)))
(setq body (cdr body))
(pcase keyw
(:prefix (setq prefix (pop body)))
(:suffix (setq suffix (pop body)))
(:directory (setq directory (pop body)))
(:text (setq text (pop body)))
(_ (push keyw extra-keywords) (pop body))))
(when extra-keywords
(error "Invalid keywords: %s" (mapconcat #'symbol-name extra-keywords " ")))
(let ((temp-file (make-symbol "temp-file"))
(prefix (or prefix ert-temp-file-prefix))
(suffix (or suffix ert-temp-file-suffix)))
`(let* ((,temp-file (,(if directory 'file-name-as-directory 'identity)
(make-temp-file ,prefix ,directory ,suffix ,text)))
(,name ,temp-file))
(unwind-protect
(progn ,@body)
(ignore-errors
,(if directory
`(delete-directory ,temp-file :recursive)
`(delete-file ,temp-file))))))))
(defmacro ert-with-temp-directory (name &rest body)
"Bind NAME to the name of a new temporary directory and evaluate BODY.
Delete the temporary directory after BODY exits normally or
non-locally.
NAME is bound to the directory name, not the directory file
name. (In other words, it will end with the directory delimiter;
on Unix-like systems, it will end with \"/\".)
The same keyword arguments are supported as in
`ert-with-temp-file' (which see), except for :text."
(declare (indent 1) (debug (symbolp body)))
(let ((tail body) keyw)
(while (keywordp (setq keyw (car tail)))
(setq tail (cddr tail))
(pcase keyw (:text (error "Invalid keyword for directory: :text")))))
`(ert-with-temp-file ,name
:directory t
,@body))
(provide 'ert-x)
;;; ert-x.el ends here

View file

@ -271,6 +271,52 @@ desired effect."
(cl-loop for x in '(0 1 2 3 4 t) do
(should (equal (c x) (lisp x))))))
(ert-deftest ert-x-tests-with-temp-file ()
(let (saved)
(ert-with-temp-file fil
(setq saved fil)
(should (file-exists-p fil))
(should (file-regular-p fil)))
(should-not (file-exists-p saved))))
(ert-deftest ert-x-tests-with-temp-file/handle-error ()
(let (saved)
(ignore-errors
(ert-with-temp-file fil
(setq saved fil)
(error "foo")))
(should-not (file-exists-p saved))))
(ert-deftest ert-x-tests-with-temp-file/prefix-and-suffix-kwarg ()
(ert-with-temp-file fil
:prefix "foo"
:suffix "bar"
(should (string-match "foo.*bar" fil))))
(ert-deftest ert-x-tests-with-temp-file/text-kwarg ()
(ert-with-temp-file fil
:text "foobar3"
(let ((buf (find-file-noselect fil)))
(unwind-protect
(with-current-buffer buf
(should (equal (buffer-string) "foobar3")))
(kill-buffer buf)))))
(ert-deftest ert-x-tests-with-temp-file/unknown-kwarg-signals-error ()
(should-error
(ert-with-temp-file fil :foo "foo" nil)))
(ert-deftest ert-x-tests-with-temp-directory ()
(let (saved)
(ert-with-temp-directory dir
(setq saved dir)
(should (file-exists-p dir))
(should (file-directory-p dir)))
(should-not (file-exists-p saved))))
(ert-deftest ert-x-tests-with-temp-directory/text-signals-error ()
(should-error
(ert-with-temp-directory dir :text "foo" nil)))
(provide 'ert-x-tests)