Subject: bug#43792: [PATCH] Add ert macros to get resource file names

From: Stefan Kangas <[email-masked]>
Date: Sun, 4 Oct 2020 12:40:33 +0000

Severity: wishlist

There's a lot of repetitive code to get at the resource directories for
tests.  That's obviously boring, so I'd propose something like the
following two macros to make it easier:

(ert-resource-directory)
(ert-resource-file NAME)

Please see the attached patch, the second of which uses the macros in
our test suite.  Not sure if they should be in ert.el, so I put them in
ert-x.el for now to play it safe.

Any comments?
From 7e0ef8e73b63e57c74102e19230dd347c5ea96d5 Mon Sep 17 00:00:00 2001
From: Stefan Kangas <[email-masked]>
Date: Wed, 23 Sep 2020 23:06:02 +0200
Subject: [PATCH 1/2] Add ert macros to get resource file names

* lisp/emacs-lisp/ert-x.el (subr-x): Require.
(ert-resource-dir, ert-resource-file): New macros to get the file name
of the resource directory belonging to a test.
(ert-resource-dir-format, ert-resource-dir-trim-left-regexp)
(ert-resource-dir-trim-right-regexp): New variables.
---
 lisp/emacs-lisp/ert-x.el | 40 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/lisp/emacs-lisp/ert-x.el b/lisp/emacs-lisp/ert-x.el
index 6569b8ccc8..abbff6da62 100644
--- a/lisp/emacs-lisp/ert-x.el
+++ b/lisp/emacs-lisp/ert-x.el
@@ -30,6 +30,7 @@
 
 (eval-when-compile (require 'cl-lib))
 (require 'ert)
+(require 'subr-x) ; string-trim

 ;;; Test buffers.
@@ -353,6 +354,45 @@ ert--make-print-advice
                            (funcall func object)))
       (funcall func object printcharfun))))
 
+(defvar ert-resource-directory-format "%s-resources/"
+  "Format for `ert-resource-directory'.")
+(defvar ert-resource-directory-trim-left-regexp ""
+  "Regexp for `string-trim' (left) used by `ert-resource-directory'.")
+(defvar ert-resource-directory-trim-right-regexp "\\(-tests?\\)?\\.el"
+  "Regexp for `string-trim' (right) used by `ert-resource-directory'.")
+
+;; Has to be a macro for `load-file-name'.
+(defmacro ert-resource-directory ()
+  "Return absolute file name of the resource directory for this file.
+
+The path to the resource directory is the \"resources\" directory
+in the same directory as the test file.
+
+If that directory doesn't exist, use the directory named like the
+test file but formatted by `ert-resource-directory-format' and trimmed
+using `string-trim' with arguments
+`ert-resource-directory-trim-left-regexp' and
+`ert-resource-directory-trim-right-regexp'.  The default values mean
+that if called from a test file named \"foo-tests.el\", return
+the absolute file name for \"foo-resources\"."
+  `(let* ((testfile ,(or (bound-and-true-p byte-compile-current-file)
+                         (and load-in-progress load-file-name)
+                         buffer-file-name))
+          (default-directory (file-name-directory testfile)))
+     (file-truename
+      (if (file-accessible-directory-p "resources/")
+          (expand-file-name "resources/")
+        (expand-file-name
+         (format ert-resource-directory-format
+                 (string-trim testfile
+                              ert-resource-directory-trim-left-regexp
+                              ert-resource-directory-trim-right-regexp)))))))
+
+(defmacro ert-resource-file (file)
+  "Return file name of resource file named FILE.
+A resource file is in the resource directory as per
+`ert-resource-directory'."
+  `(expand-file-name ,file (ert-resource-directory)))
 
 (provide 'ert-x)
 
-- 
2.28.0

From 87c5ffccafb4d63792ace0627646d9473bbc62d1 Mon Sep 17 00:00:00 2001
From: Stefan Kangas <[email-masked]>
Date: Thu, 24 Sep 2020 02:05:58 +0200
Subject: [PATCH 2/2] Use new resource directory macros in tests

* test/lisp/bookmark-tests.el (bookmark-tests-data-dir):
* test/lisp/calendar/todo-mode-tests.el (todo-test-data-dir):
* test/lisp/emacs-lisp/edebug-tests.el
(edebug-tests-sample-code-file):
* test/lisp/emacs-lisp/package-tests.el
(package-test-fake-contents-file):
* test/lisp/emacs-lisp/shadow-tests.el (shadow-tests-data-directory):
* test/lisp/emacs-lisp/testcover-tests.el
(testcover-tests-file-dir, testcover-tests-test-cases):
* test/lisp/mail/uudecode-tests.el (uudecode-tests-data-dir):
* test/lisp/net/tramp-archive-tests.el
(tramp-archive-test-resource-directory):
* test/lisp/pcmpl-linux-tests.el (pcmpl-linux-tests-data-dir):
* test/lisp/progmodes/cperl-mode-tests.el
(cperl-mode-tests-data-directory):
* test/lisp/progmodes/flymake-tests.el
(flymake-tests-data-directory):
* test/lisp/progmodes/ruby-mode-tests.el (ruby-mode-tests-data-dir):
* test/lisp/saveplace-tests.el (saveplace-tests-dir):
* test/lisp/textmodes/css-mode-tests.el (css-mode-tests-data-dir):
Remove.

* test/lisp/bookmark-tests.el (bookmark-tests-bookmark-file)
(bookmark-tests-example-file, bookmark-tests-bookmark-file-list):
* test/lisp/calendar/todo-mode-tests.el (todo-test-file-1)
(todo-test-archive-1, with-todo-test, todo-test--add-file):
* test/lisp/custom-tests.el (custom--test-theme-variables):
* test/lisp/emacs-lisp/edebug-tests.el (edebug-tests-setup-code-file):
* test/lisp/emacs-lisp/package-tests.el (package-test-data-dir)
(package-test-desc-from-buffer, package-test-install-single)
(package-test-macro-compilation)
(package-test-install-prioritized)
(package-test-install-multifile, package-test-update-archives)
(package-test-update-archives-async)
(package-test-update-archives/ignore-nil-entry)
(package-test-signed, package-x-test-upload-buffer)
(package-x-test-upload-new-version):
* test/lisp/emacs-lisp/shadow-tests.el (shadow-case-insensitive):
* test/lisp/emacs-lisp/testcover-tests.el
(testcover-tests-build-test-cases):
* test/lisp/mail/uudecode-tests.el (uudecode-tests-encoded-str)
(uudecode-tests-decoded-str):
* test/lisp/net/tramp-archive-tests.el
(tramp-archive-test-file-archive)
(tramp-archive-test-directory):
* test/lisp/pcmpl-linux-tests.el (pcmpl-linux-test-fs-types)
(pcmpl-linux-test-mounted-directories):
* test/lisp/progmodes/cperl-mode-tests.el (cperl-mode-test-bug-10483)
(cperl-mode-test-indent-styles):
* test/lisp/progmodes/flymake-tests.el
(flymake-tests--call-with-fixture):
* test/lisp/progmodes/ruby-mode-tests.el
(ruby--indent/converted-from-manual-test):
* test/lisp/saveplace-tests.el
(saveplace-test-save-place-to-alist/dir)
(saveplace-test-load-alist-from-file):
* test/lisp/textmodes/css-mode-tests.el (css-mode-test-indent): Adjust
to use new resource directory macros.
---
 test/lisp/bookmark-tests.el             | 16 +++--------
 test/lisp/calendar/todo-mode-tests.el   | 17 +++---------
 test/lisp/custom-tests.el               |  6 ++--
 test/lisp/emacs-lisp/edebug-tests.el    | 13 +--------
 test/lisp/emacs-lisp/package-tests.el   | 37 ++++++++++---------------
 test/lisp/emacs-lisp/shadow-tests.el    | 21 +++++---------
 test/lisp/emacs-lisp/testcover-tests.el | 20 ++-----------
 test/lisp/mail/uudecode-tests.el        | 14 ++--------
 test/lisp/net/tramp-archive-tests.el    | 19 ++-----------
 test/lisp/pcmpl-linux-tests.el          | 14 ++--------
 test/lisp/progmodes/cperl-mode-tests.el | 15 ++--------
 test/lisp/progmodes/flymake-tests.el    | 11 ++------
 test/lisp/progmodes/ruby-mode-tests.el  | 10 ++-----
 test/lisp/saveplace-tests.el            | 15 ++++------
 test/lisp/textmodes/css-mode-tests.el   | 10 ++-----
 test/lisp/url/url-file-tests.el         | 11 ++------
 16 files changed, 60 insertions(+), 189 deletions(-)

diff --git a/test/lisp/bookmark-tests.el b/test/lisp/bookmark-tests.el
index c5959e46d8..7cfd4ac14f 100644
--- a/test/lisp/bookmark-tests.el
+++ b/test/lisp/bookmark-tests.el
@@ -24,24 +24,17 @@
 ;;; Code:
 
 (require 'ert)
+(require 'ert-x)
 (require 'bookmark)
 (require 'cl-lib)
 
-(defvar bookmark-tests-data-dir
-  (file-truename
-   (expand-file-name "bookmark-resources/"
-                     (file-name-directory (or load-file-name
-                                              buffer-file-name))))
-  "Base directory of bookmark-tests.el data files.")
-
-(defvar bookmark-tests-bookmark-file
-  (expand-file-name "test.bmk" bookmark-tests-data-dir)
+(defvar bookmark-tests-bookmark-file (ert-resource-file "test.bmk")
   "Bookmark file used for testing.")
 
 (defvar bookmark-tests-example-file
   ;; We use abbreviate-file-name here to match the behavior of
   ;; `bookmark-buffer-file-name'.
-  (abbreviate-file-name (expand-file-name "example.txt" bookmark-tests-data-dir))
+  (abbreviate-file-name (ert-resource-file "example.txt"))
   "Example file used for testing.")
 
 ;; The values below should match `bookmark-tests-bookmark-file'.  We cache
@@ -83,8 +76,7 @@ with-bookmark-test-file
           ,@body)
        (kill-buffer buffer))))
 
-(defvar bookmark-tests-bookmark-file-list
-  (expand-file-name "test-list.bmk" bookmark-tests-data-dir)
+(defvar bookmark-tests-bookmark-file-list (ert-resource-file "test-list.bmk")
   "Bookmark file used for testing a list of bookmarks.")
 
 ;; The values below should match `bookmark-tests-bookmark-file-list'
diff --git a/test/lisp/calendar/todo-mode-tests.el b/test/lisp/calendar/todo-mode-tests.el
index 1fbd39478c..6ed5512198 100644
--- a/test/lisp/calendar/todo-mode-tests.el
+++ b/test/lisp/calendar/todo-mode-tests.el
@@ -28,19 +28,10 @@
 (require 'ert-x)
 (require 'todo-mode)
 
-(defvar todo-test-data-dir
-  (file-truename
-   (expand-file-name "todo-mode-resources/"
-                     (file-name-directory (or load-file-name
-                                              buffer-file-name))))
-  "Base directory of todo-mode.el test data files.")
-
-(defvar todo-test-file-1 (expand-file-name "todo-test-1.todo"
-                                           todo-test-data-dir)
+(defvar todo-test-file-1 (ert-resource-file "todo-test-1.todo")
   "Todo mode test file.")
 
-(defvar todo-test-archive-1 (expand-file-name "todo-test-1.toda"
-                                              todo-test-data-dir)
+(defvar todo-test-archive-1 (ert-resource-file "todo-test-1.toda")
   "Todo Archive mode test file.")
 
 (defmacro with-todo-test (&rest body)
@@ -52,7 +43,7 @@ with-todo-test
           (abbreviated-home-dir nil)
           (process-environment (cons (format "HOME=%s" todo-test-home)
                                      process-environment))
-          (todo-directory todo-test-data-dir)
+          (todo-directory (ert-resource-directory))
           (todo-default-todo-file (todo-short-file-name
 				   (car (funcall todo-files-function)))))
      (unwind-protect
@@ -815,7 +806,7 @@ todo-test--add-file
   "Add file FILE with category CAT to todo-files and show it.
 This provides a noninteractive API for todo-add-file for use in
 automatic testing."
-  (let ((file0 (file-truename (concat todo-test-data-dir file ".todo")))
+  (let ((file0 (ert-resource-file (concat file ".todo")))
         todo-add-item-if-new-category)  ; Don't need an item in cat.
     (cl-letf (((symbol-function 'todo-read-file-name)
                (lambda (_prompt) file0))
diff --git a/test/lisp/custom-tests.el b/test/lisp/custom-tests.el
index 76661dc13b..a1451cf0ce 100644
--- a/test/lisp/custom-tests.el
+++ b/test/lisp/custom-tests.el
@@ -20,6 +20,7 @@
 ;;; Code:
 
 (require 'ert)
+(require 'ert-x)
 
 (require 'wid-edit)
 (require 'cus-edit)
@@ -100,10 +101,7 @@ custom--test-variable
 (ert-deftest custom--test-theme-variables ()
   "Test variables setting with enabling / disabling a custom theme."
   ;; We load custom-resources/custom--test-theme.el.
-  (let ((custom-theme-load-path
-         `(,(expand-file-name
-	     "custom-resources"
-	     (expand-file-name "lisp" (getenv "EMACS_TEST_DIRECTORY"))))))
+  (let ((custom-theme-load-path `(,(ert-resource-directory))))
     (load-theme 'custom--test 'no-confirm 'no-enable)
     ;; The variables have still their initial values.
     (should (equal custom--test-user-option 'foo))
diff --git a/test/lisp/emacs-lisp/edebug-tests.el b/test/lisp/emacs-lisp/edebug-tests.el
index 6db07b1b70..6993978ac5 100644
--- a/test/lisp/emacs-lisp/edebug-tests.el
+++ b/test/lisp/emacs-lisp/edebug-tests.el
@@ -36,17 +36,6 @@
 (require 'edebug)
 (require 'kmacro)
 
-;; Use `eval-and-compile' because this is used by the macro
-;; `edebug-tests-deftest'.
-(eval-and-compile
-  (defvar edebug-tests-sample-code-file
-    (expand-file-name
-     "edebug-resources/edebug-test-code.el"
-     (file-name-directory (or (bound-and-true-p byte-compile-current-file)
-                              load-file-name
-                              buffer-file-name)))
-    "Name of file containing code samples for Edebug tests."))
-
 (defvar edebug-tests-temp-file nil
   "Name of temp file containing sample code stripped of stop point symbols.")
 (defvar edebug-tests-stop-points nil
@@ -344,7 +333,7 @@ edebug-tests-setup-code-file
 Write the loadable code to a buffer for TMPFILE, and set
 `edebug-tests-stop-points' to a map from defined symbols to stop
 point names to positions in the file."
-  (with-current-buffer (find-file-noselect edebug-tests-sample-code-file)
+  (with-current-buffer (find-file-noselect (ert-resource-file "edebug-test-code.el"))
     (let ((marked-up-code (buffer-string)))
       (with-temp-file tmpfile
         (insert marked-up-code))))
diff --git a/test/lisp/emacs-lisp/package-tests.el b/test/lisp/emacs-lisp/package-tests.el
index cbb2410f95..155a8e6fce 100644
--- a/test/lisp/emacs-lisp/package-tests.el
+++ b/test/lisp/emacs-lisp/package-tests.el
@@ -39,6 +39,7 @@
 
 (require 'package)
 (require 'ert)
+(require 'ert-x)
 (require 'cl-lib)
 
 (setq package-menu-async nil)
@@ -102,13 +103,9 @@ simple-depend-desc-2
                                (multi-file (0 1))))
   "`package-desc' used for testing dependencies.")
 
-(defvar package-test-data-dir (expand-file-name "package-resources" package-test-file-dir)
+(defvar package-test-data-dir (ert-resource-directory)
   "Base directory of package test files.")
 
-(defvar package-test-fake-contents-file
-  (expand-file-name "archive-contents" package-test-data-dir)
-  "Path to a static copy of \"archive-contents\".")
-
 (cl-defmacro with-package-test ((&optional &key file
                                            basedir
                                            install
@@ -215,20 +212,20 @@ package-test--compatible-p
 
 (ert-deftest package-test-desc-from-buffer ()
   "Parse an elisp buffer to get a `package-desc' object."
-  (with-package-test (:basedir "package-resources" :file "simple-single-1.3.el")
+  (with-package-test (:basedir (ert-resource-directory) :file "simple-single-1.3.el")
     (should (package-test--compatible-p
              (package-buffer-info) simple-single-desc 'kind)))
-  (with-package-test (:basedir "package-resources" :file "simple-depend-1.0.el")
+  (with-package-test (:basedir (ert-resource-directory) :file "simple-depend-1.0.el")
     (should (package-test--compatible-p
              (package-buffer-info) simple-depend-desc 'kind)))
-  (with-package-test (:basedir "package-resources"
+  (with-package-test (:basedir (ert-resource-directory)
                                :file "multi-file-0.2.3.tar")
     (tar-mode)
     (should (equal (package-tar-file-info) multi-file-desc))))
 
 (ert-deftest package-test-install-single ()
   "Install a single file without using an archive."
-  (with-package-test (:basedir "package-resources" :file "simple-single-1.3.el")
+  (with-package-test (:basedir (ert-resource-directory) :file "simple-single-1.3.el")
     (should (package-install-from-buffer))
     (package-initialize)
     (should (package-installed-p 'simple-single))
@@ -271,7 +268,7 @@ package-test-install-dependency
 
 (ert-deftest package-test-macro-compilation ()
   "Install a package which includes a dependency."
-  (with-package-test (:basedir "package-resources")
+  (with-package-test (:basedir (ert-resource-directory))
     (package-install-file (expand-file-name "macro-problem-package-1.0/"))
     (require 'macro-problem)
     ;; `macro-problem-func' uses a macro from `macro-aux'.
@@ -310,8 +307,7 @@ package-test-install-single-from-archive
 (ert-deftest package-test-install-prioritized ()
   "Install a lower version from a higher-prioritized archive."
   (with-package-test ()
-    (let* ((newer-version (expand-file-name "package-resources/newer-versions"
-                                            package-test-file-dir))
+    (let* ((newer-version (ert-resource-file "newer-versions"))
            (package-archives `(("older" . ,package-test-data-dir)
                                ("newer" . ,newer-version)))
            (package-archive-priorities '(("older" . 100))))
@@ -326,7 +322,7 @@ package-test-install-prioritized
 
 (ert-deftest package-test-install-multifile ()
   "Check properties of the installed multi-file package."
-  (with-package-test (:basedir "package-resources" :install '(multi-file))
+  (with-package-test (:basedir (ert-resource-directory) :install '(multi-file))
     (let ((autoload-file
            (expand-file-name "multi-file-autoloads.el"
                              (expand-file-name
@@ -472,8 +468,7 @@ package-test-update-archives
       (package-menu-mark-install)
       (package-menu-execute)
       (should (package-installed-p 'simple-single))
-      (let ((package-test-data-dir
-             (expand-file-name "package-resources/newer-versions" package-test-file-dir)))
+      (let ((package-test-data-dir (ert-resource-file "newer-versions")))
         (setq package-archives `(("gnu" . ,package-test-data-dir)))
         (revert-buffer)
 
@@ -512,7 +507,7 @@ package-test-update-archives-async
                  (when (re-search-forward "Server started, \\(.*\\)\n" nil t)
                    (setq addr (match-string 1))))
                addr)))
-          (with-package-test (:basedir package-test-data-dir :location addr)
+          (with-package-test (:basedir (ert-resource-directory) :location addr)
             (list-packages)
             (should package--downloads-in-progress)
             (should mode-line-process)
@@ -532,8 +527,7 @@ package-test-update-archives-async
 (ert-deftest package-test-update-archives/ignore-nil-entry ()
   "Ignore any packages that are nil.  Test for Bug#28502."
   (with-package-test ()
-    (let* ((with-nil-entry (expand-file-name "package-resources/with-nil-entry"
-                                             package-test-file-dir))
+    (let* ((with-nil-entry (ert-resource-file "with-nil-entry"))
            (package-archives `(("with-nil-entry" . ,with-nil-entry))))
       (package-initialize)
       (package-refresh-contents)
@@ -634,8 +628,7 @@ package-test-signed
                           prog-alist)))
 		   (delete-directory homedir t))))
   (let* ((keyring (expand-file-name "key.pub" package-test-data-dir))
-	 (package-test-data-dir
-	   (expand-file-name "package-resources/signed" package-test-file-dir)))
+         (package-test-data-dir (ert-resource-file "signed")))
     (with-package-test ()
       (package-initialize)
       (package-import-keyring keyring)
@@ -696,7 +689,7 @@ package-x-test--single-archive-entry-1-4
 
 (ert-deftest package-x-test-upload-buffer ()
   "Test creating an \"archive-contents\" file"
-  (with-package-test (:basedir "package-resources"
+  (with-package-test (:basedir (ert-resource-directory)
                                :file "simple-single-1.3.el"
                                :upload-base t)
     (package-upload-buffer)
@@ -729,7 +722,7 @@ package-x-test-upload-buffer
 
 (ert-deftest package-x-test-upload-new-version ()
   "Test uploading a new version of a package"
-  (with-package-test (:basedir "package-resources"
+  (with-package-test (:basedir (ert-resource-directory)
                                :file "simple-single-1.3.el"
                                :upload-base t)
     (package-upload-buffer)
diff --git a/test/lisp/emacs-lisp/shadow-tests.el b/test/lisp/emacs-lisp/shadow-tests.el
index 219312a557..5d6215ab6f 100644
--- a/test/lisp/emacs-lisp/shadow-tests.el
+++ b/test/lisp/emacs-lisp/shadow-tests.el
@@ -20,30 +20,23 @@
 ;;; Code:
 
 (require 'ert)
+(require 'ert-x)
 (require 'shadow)
 (eval-when-compile (require 'cl-lib))
 
-(defconst shadow-tests-data-directory
-  (expand-file-name "lisp/emacs-lisp/shadow-resources"
-                    (or (getenv "EMACS_TEST_DIRECTORY")
-                        (expand-file-name "../../.."
-                                          (or load-file-name
-                                              buffer-file-name))))
-  "Directory for shadow test files.")
-
 (ert-deftest shadow-case-insensitive ()
   "Test shadowing for case insensitive filenames."
   ;; Override `file-name-case-insensitive-p' so we test the same thing
   ;; regardless of what file system we're running on.
   (cl-letf (((symbol-function 'file-name-case-insensitive-p) (lambda (_f) t)))
-    (should (equal (list (expand-file-name "p1/foo" shadow-tests-data-directory)
-                         (expand-file-name "p2/FOO" shadow-tests-data-directory))
+    (should (equal (list (ert-resource-file "p1/foo")
+                         (ert-resource-file "p2/FOO"))
                    (load-path-shadows-find
-                    (list (expand-file-name "p1/" shadow-tests-data-directory)
-                          (expand-file-name "p2/" shadow-tests-data-directory))))))
+                    (list (ert-resource-file "p1/")
+                          (ert-resource-file "p2/"))))))
   (cl-letf (((symbol-function 'file-name-case-insensitive-p) (lambda (_f) nil)))
     (should-not (load-path-shadows-find
-                 (list (expand-file-name "p1/" shadow-tests-data-directory)
-                       (expand-file-name "p2/" shadow-tests-data-directory))))))
+                 (list (ert-resource-file "p1/")
+                       (ert-resource-file "p2/"))))))
 
 ;;; shadow-tests.el ends here.
diff --git a/test/lisp/emacs-lisp/testcover-tests.el b/test/lisp/emacs-lisp/testcover-tests.el
index 6870d49acb..784367c287 100644
--- a/test/lisp/emacs-lisp/testcover-tests.el
+++ b/test/lisp/emacs-lisp/testcover-tests.el
@@ -31,26 +31,10 @@
 ;;; Code:
 
 (require 'ert)
+(require 'ert-x)
 (require 'testcover)
 (require 'skeleton)
 
-;; Use `eval-and-compile' around all these definitions because they're
-;; used by the macro `testcover-tests-define-tests'.
-
-(eval-and-compile
-  (defvar testcover-tests-file-dir
-    (expand-file-name
-     "testcover-resources/"
-     (file-name-directory (or (bound-and-true-p byte-compile-current-file)
-                              load-file-name
-                              buffer-file-name)))
-    "Directory of the \"testcover-tests.el\" file."))
-
-(eval-and-compile
-  (defvar testcover-tests-test-cases
-    (expand-file-name "testcases.el" testcover-tests-file-dir)
-    "File containing marked up code to instrument and check."))
-
 ;; Convert Testcover's overlays to plain text.
 
 (eval-and-compile
@@ -149,7 +133,7 @@ testcover-tests-skeleton
 for documentation of the test definition format."
     (let (results)
       (with-temp-buffer
-        (insert-file-contents testcover-tests-test-cases)
+        (insert-file-contents (ert-resource-file "testcases.el"))
         (goto-char (point-min))
         (while (re-search-forward
                 (concat "^;; ==== \\([^ ]+?\\) ====\n"
diff --git a/test/lisp/mail/uudecode-tests.el b/test/lisp/mail/uudecode-tests.el
index 4c9650f556..17566250a9 100644
--- a/test/lisp/mail/uudecode-tests.el
+++ b/test/lisp/mail/uudecode-tests.el
@@ -24,15 +24,9 @@
 ;;; Code:
 
 (require 'ert)
+(require 'ert-x)
 (require 'uudecode)
 
-(defvar uudecode-tests-data-dir
-  (file-truename
-   (expand-file-name "uudecode-resources/"
-                     (file-name-directory (or load-file-name
-                                              buffer-file-name))))
-  "Base directory of uudecode-tests.el test data files.")
-
 (defun uudecode-tests-read-file (file)
   "Read contents of FILE and return as string."
   (with-temp-buffer
@@ -40,13 +34,11 @@ uudecode-tests-read-file
     (buffer-string)))
 
 (defvar uudecode-tests-encoded-str
-  (uudecode-tests-read-file
-   (expand-file-name "uuencoded.txt" uudecode-tests-data-dir))
+  (uudecode-tests-read-file (ert-resource-file "uuencoded.txt"))
   "Uuencoded data for bookmark-tests.el
 Same as `uudecode-tests-decoded-str' but uuencoded.")
 (defvar uudecode-tests-decoded-str
-  (uudecode-tests-read-file
-   (expand-file-name "uudecoded.txt" uudecode-tests-data-dir))
+  (uudecode-tests-read-file (ert-resource-file "uudecoded.txt"))
   "Plain text data for bookmark-tests.el
 Same as `uudecode-tests-encoded-str' but plain text.")
 
diff --git a/test/lisp/net/tramp-archive-tests.el b/test/lisp/net/tramp-archive-tests.el
index 9a2319126a..4750852f78 100644
--- a/test/lisp/net/tramp-archive-tests.el
+++ b/test/lisp/net/tramp-archive-tests.el
@@ -27,25 +27,12 @@
 ;; tests in tramp-tests.el.
 
 (require 'ert)
+(require 'ert-x)
 (require 'tramp-archive)
 (defvar tramp-copy-size-limit)
 (defvar tramp-persistency-file-name)
 
-(defconst tramp-archive-test-resource-directory
-  (let ((default-directory
-	  (if load-in-progress
-	      (file-name-directory load-file-name)
-	    default-directory)))
-    (cond
-     ((file-accessible-directory-p (expand-file-name "resources"))
-      (expand-file-name "resources"))
-     ((file-accessible-directory-p (expand-file-name "tramp-archive-resources"))
-      (expand-file-name "tramp-archive-resources"))))
-  "The resources directory test files are located in.")
-
-(defconst tramp-archive-test-file-archive
-  (file-truename
-   (expand-file-name "foo.tar.gz" tramp-archive-test-resource-directory))
+(defconst tramp-archive-test-file-archive (ert-resource-file "foo.tar.gz")
   "The test file archive.")
 
 (defun tramp-archive-test-file-archive-hexlified ()
@@ -60,7 +47,7 @@ tramp-archive-test-archive
 
 (defconst tramp-archive-test-directory
   (file-truename
-   (expand-file-name "foo.iso" tramp-archive-test-resource-directory))
+   (ert-resource-file "foo.iso"))
   "A directory file name, which looks like an archive.")
 
 (setq password-cache-expiry nil
diff --git a/test/lisp/pcmpl-linux-tests.el b/test/lisp/pcmpl-linux-tests.el
index cf7e6288fd..91a9965483 100644
--- a/test/lisp/pcmpl-linux-tests.el
+++ b/test/lisp/pcmpl-linux-tests.el
@@ -22,25 +22,17 @@
 ;;; Code:
 
 (require 'ert)
+(require 'ert-x)
 (require 'pcmpl-linux)
 
-(defvar pcmpl-linux-tests-data-dir
-  (file-truename
-   (expand-file-name "pcmpl-linux-resources/"
-                     (file-name-directory (or load-file-name
-                                              buffer-file-name))))
-  "Base directory of pcmpl-linux-tests.el data files.")
-
 (ert-deftest pcmpl-linux-test-fs-types ()
-  (let ((pcmpl-linux-fs-modules-path-format (expand-file-name "fs"
-                                                   pcmpl-linux-tests-data-dir)))
+  (let ((pcmpl-linux-fs-modules-path-format (ert-resource-file "fs")))
     ;; FIXME: Shouldn't return "." and ".."
     (should (equal (pcmpl-linux-fs-types)
                    '("." ".." "ext4")))))
 
 (ert-deftest pcmpl-linux-test-mounted-directories ()
-  (let ((pcmpl-linux-mtab-file (expand-file-name "mtab"
-                                      pcmpl-linux-tests-data-dir)))
+  (let ((pcmpl-linux-mtab-file (ert-resource-file "mtab")))
     (should (equal (pcmpl-linux-mounted-directories)
                    '("/" "/dev" "/dev/pts" "/dev/shm" "/home/alice/.gvfs"
                      "/lib/modules/2.6.24-16-generic/volatile" "/proc" "/sys"
diff --git a/test/lisp/progmodes/cperl-mode-tests.el b/test/lisp/progmodes/cperl-mode-tests.el
index f0ff8e9005..d8811298d9 100644
--- a/test/lisp/progmodes/cperl-mode-tests.el
+++ b/test/lisp/progmodes/cperl-mode-tests.el
@@ -32,14 +32,7 @@ cperl-test-mode
 
 (require 'cperl-mode)
 (require 'ert)
-
-(defvar cperl-mode-tests-data-directory
-  (expand-file-name "lisp/progmodes/cperl-mode-resources"
-                    (or (getenv "EMACS_TEST_DIRECTORY")
-                        (expand-file-name "../../../"
-                                          (or load-file-name
-                                              buffer-file-name))))
-  "Directory containing cperl-mode test data.")
+(require 'ert-x)
 
 (defun cperl-test-ppss (text regexp)
   "Return the `syntax-ppss' of the first character matched by REGEXP in TEXT."
@@ -148,8 +141,7 @@ cperl-mode-test-indent-exp
 These exercise some standard blocks and also the special
 treatment for Perl expressions where a closing paren isn't the
 end of the statement."
-  (let ((file (expand-file-name "cperl-indent-exp.pl"
-                                cperl-mode-tests-data-directory)))
+  (let ((file (ert-resource-file "cperl-indent-exp.pl")))
     (with-temp-buffer
       (insert-file-contents file)
       (goto-char (point-min))
@@ -177,8 +169,7 @@ cperl-mode-test-indent-styles
 Perl Best Practices sets some indentation values different from
   the defaults, and also wants an \"else\" or \"elsif\" keyword
   to align with the \"if\"."
-  (let ((file (expand-file-name "cperl-indent-styles.pl"
-                                cperl-mode-tests-data-directory)))
+  (let ((file (ert-resource-file "cperl-indent-styles.pl")))
     (with-temp-buffer
       (cperl-set-style "PBP")
       (insert-file-contents file)
diff --git a/test/lisp/progmodes/flymake-tests.el b/test/lisp/progmodes/flymake-tests.el
index df72b523a9..c62a2dbde1 100644
--- a/test/lisp/progmodes/flymake-tests.el
+++ b/test/lisp/progmodes/flymake-tests.el
@@ -23,17 +23,10 @@
 
 ;;; Code:
 (require 'ert)
+(require 'ert-x)
 (require 'flymake)
 (eval-when-compile (require 'subr-x)) ; string-trim
 
-(defvar flymake-tests-data-directory
-  (expand-file-name "lisp/progmodes/flymake-resources"
-                    (or (getenv "EMACS_TEST_DIRECTORY")
-                        (expand-file-name "../../.."
-                                          (or load-file-name
-                                              buffer-file-name))))
-  "Directory containing flymake test data.")
-
 
 ;;
 ;;
@@ -63,7 +56,7 @@ flymake-tests--call-with-fixture
   "Call FN after flymake setup in FILE, using `flymake-proc`.
 SEVERITY-PREDICATE is used to setup
 `flymake-proc-diagnostic-type-pred'"
-  (let* ((file (expand-file-name file flymake-tests-data-directory))
+  (let* ((file (ert-resource-file file))
          (visiting (find-buffer-visiting file))
          (buffer (or visiting (find-file-noselect file)))
          (process-environment (cons "LC_ALL=C" process-environment))
diff --git a/test/lisp/progmodes/ruby-mode-tests.el b/test/lisp/progmodes/ruby-mode-tests.el
index 5988a49523..369a93e2f5 100644
--- a/test/lisp/progmodes/ruby-mode-tests.el
+++ b/test/lisp/progmodes/ruby-mode-tests.el
@@ -22,14 +22,9 @@
 ;;; Code:
 
 (require 'ert)
+(require 'ert-x)
 (require 'ruby-mode)
 
-(defvar ruby-mode-tests-data-dir
-  (file-truename
-   (expand-file-name "ruby-mode-resources/"
-                     (file-name-directory (or load-file-name
-                                              buffer-file-name)))))
-
 (defmacro ruby-with-temp-buffer (contents &rest body)
   (declare (indent 1) (debug t))
   `(with-temp-buffer
@@ -851,8 +846,7 @@ ruby--insert-coding-comment-custom-style
 (ert-deftest ruby--indent/converted-from-manual-test ()
   :tags '(:expensive-test)
   ;; Converted from manual test.
-  (let ((buf (find-file-noselect (expand-file-name "ruby.rb"
-                                                   ruby-mode-tests-data-dir))))
+  (let ((buf (find-file-noselect (ert-resource-file "ruby.rb"))))
     (unwind-protect
         (with-current-buffer buf
           (let ((orig (buffer-string)))
diff --git a/test/lisp/saveplace-tests.el b/test/lisp/saveplace-tests.el
index ae7749fe93..27aa2ec192 100644
--- a/test/lisp/saveplace-tests.el
+++ b/test/lisp/saveplace-tests.el
@@ -22,25 +22,20 @@
 ;;; Commentary:
 
 (require 'ert)
+(require 'ert-x)
 (require 'saveplace)
 
-(defvar saveplace-tests-dir
-  (file-truename
-   (expand-file-name "saveplace-resources"
-                     (file-name-directory (or load-file-name
-                                              buffer-file-name)))))
-
 (ert-deftest saveplace-test-save-place-to-alist/dir ()
   (save-place-mode)
   (let* ((save-place-alist nil)
          (save-place-loaded t)
-         (loc saveplace-tests-dir))
+         (loc (ert-resource-directory)))
     (save-window-excursion
       (dired loc)
       (save-place-to-alist)
       (should (equal save-place-alist
-                     `((,(concat loc "/")
-                        (dired-filename . ,(concat loc "/saveplace")))))))))
+                     `((,loc
+                        (dired-filename . ,(concat loc "saveplace")))))))))
 
 (ert-deftest saveplace-test-save-place-to-alist/file ()
   (save-place-mode)
@@ -91,7 +86,7 @@ saveplace-test-load-alist-from-file
   (save-place-mode)
   (let ((save-place-loaded nil)
         (save-place-file
-         (expand-file-name "saveplace" saveplace-tests-dir))
+         (ert-resource-file "saveplace"))
         (save-place-alist nil))
     (load-save-place-alist-from-file)
     (should (equal save-place-alist
diff --git a/test/lisp/textmodes/css-mode-tests.el b/test/lisp/textmodes/css-mode-tests.el
index f627d1c02c..476fd326e6 100644
--- a/test/lisp/textmodes/css-mode-tests.el
+++ b/test/lisp/textmodes/css-mode-tests.el
@@ -28,14 +28,9 @@
 
 (require 'css-mode)
 (require 'ert)
+(require 'ert-x)
 (require 'seq)
 
-(defvar css-mode-tests-data-dir
-  (file-truename
-   (expand-file-name "css-mode-resources/"
-                     (file-name-directory (or load-file-name
-                                              buffer-file-name)))))
-
 (ert-deftest css-test-property-values ()
   ;; The `float' property has a flat value list.
   (should
@@ -419,8 +414,7 @@ css-test-named-color
 
 (ert-deftest css-mode-test-indent ()
   (with-current-buffer
-      (find-file-noselect (expand-file-name "test-indent.css"
-                                            css-mode-tests-data-dir))
+      (find-file-noselect (ert-resource-file "test-indent.css"))
     (let ((orig (buffer-string)))
       (indent-region (point-min) (point-max))
       (should (equal (buffer-string) orig)))))
diff --git a/test/lisp/url/url-file-tests.el b/test/lisp/url/url-file-tests.el
index e4a45fb9c8..810504faf2 100644
--- a/test/lisp/url/url-file-tests.el
+++ b/test/lisp/url/url-file-tests.el
@@ -23,18 +23,11 @@
 
 (require 'url-file)
 (require 'ert)
-
-(defconst url-file-tests-data-directory
-  (expand-file-name "lisp/url/url-file-resources"
-                    (or (getenv "EMACS_TEST_DIRECTORY")
-                        (expand-file-name "../../.."
-                                          (or load-file-name
-                                              buffer-file-name))))
-  "Directory for url-file test files.")
+(require 'ert-x)
 
 (ert-deftest url-file ()
   "Test reading file via file:/// URL."
-  (let* ((file (expand-file-name "file.txt" url-file-tests-data-directory))
+  (let* ((file (ert-resource-file "file.txt"))
          (uri-prefix (if (eq (aref file 0) ?/) "file://" "file:///")))
     (should (equal
              (with-current-buffer
-- 
2.28.0