branch: externals/matlab-mode
commit decea985e47ad62ff2308fbd253b8d13bfc78104
Author: John Ciolfi <john.ciolfi...@gmail.com>
Commit: John Ciolfi <john.ciolfi...@gmail.com>

    matlab-ts-mode: update tests to use ert, fix electric pair issue
    
    With the latest matlab tree-sitter parser, items like
    
      s = '
    
    are now (correctly) have ERROR nodes. This updates the electric-pair 
handling to support that.
---
 contributing/treesit-mode-how-to.org               | 591 +++------------
 matlab-ts-mode.el                                  |  11 +-
 tests/metest.el                                    |   2 +-
 tests/t-utils.el                                   | 804 +++++++++++++--------
 tests/test-matlab-ts-mode-comments.el              |  31 +-
 tests/test-matlab-ts-mode-electric-pair.el         |  33 +-
 tests/test-matlab-ts-mode-fill-paragraph.el        |  29 +-
 tests/test-matlab-ts-mode-font-lock.el             |  90 +--
 tests/test-matlab-ts-mode-imenu.el                 |  29 +-
 tests/test-matlab-ts-mode-indent.el                |  52 +-
 tests/test-matlab-ts-mode-on-save-fixes.el         |  34 +-
 tests/test-matlab-ts-mode-outline.el               |  33 +-
 tests/test-matlab-ts-mode-page.el                  |  33 +-
 .../show_paren_string.m                            |   7 +-
 .../show_paren_string_expected.org                 |  93 ++-
 tests/test-matlab-ts-mode-show-paren.el            |  27 +-
 tests/test-matlab-ts-mode-syntax-table.el          |  28 +-
 tests/test-matlab-ts-mode-thing-settings.el        |  34 +-
 tests/test-matlab-ts-mode-treesit-defun-name.el    |  32 +-
 19 files changed, 941 insertions(+), 1052 deletions(-)

diff --git a/contributing/treesit-mode-how-to.org 
b/contributing/treesit-mode-how-to.org
index d9e47e7669..fd6497a52c 100644
--- a/contributing/treesit-mode-how-to.org
+++ b/contributing/treesit-mode-how-to.org
@@ -369,58 +369,47 @@ To run your tests in a build system, use
 #+end_src
 
 #+begin_src emacs-lisp
-  ;;; test-LANGUAGE-ts-mode-font-lock.el --- Test LANGUAGE-ts-mode font-lock 
-*- lexical-binding: t -*-
-
-  ;;; Commentary:
-
-  ;;; Code:
-
   (require 't-utils)
   (require 'language-ts-mode)
 
-  (cl-defun test-language-ts-mode-font-lock (&optional lang-file)
-    "Test font-lock using ./test-language-ts-mode-font-lock-files/NAME.lang.
-  Compare ./test-language-ts-mode-font-lock-files/NAME.lang against
-  ./test-language-ts-mode-font-lock-files/NAME_expected.txt, where
+  (defvar test-LANGUAGE-ts-mode-font-lock--file nil)
+
+  (defun test-LANGUAGE-ts-mode-font-lock--file (lang-file)
+    "Test an individual LANG-FILE.
+  This is provided for debugging.
+    M-: (test-LANGUAGE-ts-mode-font-lock--file 
\"test-LANGUAGE-ts-mode-font-lock-files/LANG-FILE\")"
+    (let ((test-LANGUAGE-ts-mode-font-lock--file lang-file))
+      (ert-run-tests-interactively "test-LANGUAGE-ts-mode-font-lock")))
+
+  (ert-deftest test-LANGUAGE-ts-mode-font-lock ()
+    "Test font-lock using ./test-LANGUAGE-ts-mode-font-lock-files/NAME.lang.
+  Compare font of ./test-LANGUAGE-ts-mode-font-lock-files/NAME.lang against
+  ./test-LANGUAGE-ts-mode-font-lock-files/NAME_expected.txt, where
   NAME_expected.txt is of same length as NAME.lang where each source
   character in NAME.lang is replaced with a character code representing the
   font-lock face used for said source character.  The mapping is defined
-  by the code-to-face alist setup by this function.  If LANG-FILE is not
-  provided, loop comparing all
-  ./test-language-ts-mode-font-lock-files/NAME.lang files.
+  by the code-to-face alist setup by this function.  This loops
+  on all ./test-LANGUAGE-ts-mode-font-lock-files/NAME.lang files.
 
-  To add a test, create
-    ./test-language-ts-mode-font-lock-files/NAME.lang
+  To add a test, createp
+    ./test-LANGUAGE-ts-mode-font-lock-files/NAME.lang
   and run this function.  The baseline is saved for you as
-    ./test-language-ts-mode-font-lock-files/NAME_expected.lang~
+    ./test-LANGUAGE-ts-mode-font-lock-files/NAME_expected.txt~
   after validating it, rename it to
-    ./test-language-ts-mode-font-lock-files/NAME_expected.lang"
-
-    (let ((test-name "test-language-ts-mode-font-lock"))
-      (when (not (t-utils-is-treesit-available 'language test-name))
-        (cl-return-from test-language-ts-mode-font-lock))
-
-      (let* ((lang-files (t-utils-get-files (concat test-name "-files") 
"\\.lang$" nil lang-file))
-             (code-to-face '(
-                             ("b" . font-lock-bracket-face)
-                             ("B" . font-lock-builtin-face)
-                             ("c" . font-lock-comment-face)
-                             ("C" . font-lock-comment-delimiter-face)
-                             ("d" . default)
-                             ("D" . font-lock-delimiter-face)
-                             ("f" . font-lock-function-name-face)
-                             ("h" . font-lock-doc-face)
-                             ("k" . font-lock-keyword-face)
-                             ("n" . font-lock-constant-face)
-                             ("s" . font-lock-string-face)
-                             ("P" . font-lock-property-name-face)
-                             ("t" . font-lock-type-face)
-                             ("v" . font-lock-variable-name-face)
-                             ("w" . font-lock-warning-face)
-                             )))
-        (t-utils-test-font-lock test-name lang-files code-to-face))
-      ;; return "success" for M-: (test-language-ts-mode-font-lock)
-      "success"))
+    ./test-LANGUAGE-ts-mode-font-lock-files/NAME_expected.txt"
+
+    (let ((test-name "test-LANGUAGE-ts-mode-font-lock"))
+      (when (t-utils-is-treesit-available 'LANGUAGE test-name)
+        (let* ((LANGUAGE-ts-mode-font-lock-level 4)
+               (lang-files (t-utils-get-files (concat test-name "-files") 
"\\.lang\\'" nil
+                                           
test-LANGUAGE-ts-mode-font-lock--file))
+               (code-to-face '(
+                               ("b" . font-lock-bracket-face)
+                               ("B" . font-lock-builtin-face)
+                               ("c" . font-lock-comment-face)
+                            ;; <add more as needed>
+                               )))
+          (t-utils-test-font-lock test-name lang-files code-to-face)))))
 
   (provide 'test-language-ts-mode-font-lock)
   ;;; test-language-ts-mode-font-lock.el ends here
@@ -728,21 +717,24 @@ We use a similar pattern for our indent tests:
 where test-LANGUAGE-ts-mode-indent.el contains:
 
 #+begin_src emacs-lisp
-  ;;; test-LANGUAGE-ts-mode-indent.el --- Test LANGUAGE-ts-mode indent -*- 
lexical-binding: t -*-
-
-  ;;; Commentary:
-
-  ;;; Code:
-
   (require 't-utils)
   (require 'LANGUAGE-ts-mode)
 
-  (cl-defun test-LANGUAGE-ts-mode-indent (&optional lang-file)
+  (defvar test-LANGUAGE-ts-mode-indent--file nil)
+
+  (defun test-LANGUAGE-ts-mode-indent--file (lang-file)
+    "Test an individual LANG-FILE.
+  This is provided for debugging.
+    M-: (test-LANGUAGE-ts-mode-indent--file 
\"test-LANGUAGE-ts-mode-indent-files/LANG-FILE\")"
+    (let ((test-LANGUAGE-ts-mode-indent--file lang-file))
+      (ert-run-tests-interactively "test-LANGUAGE-ts-mode-indent")))
+
+  (ert-deftest test-LANGUAGE-ts-mode-indent ()
     "Test indent using ./test-LANGUAGE-ts-mode-indent-files/NAME.lang.
   Compare indent of ./test-LANGUAGE-ts-mode-indent-files/NAME.lang against
   ./test-LANGUAGE-ts-mode-indent-files/NAME_expected.lang.  Indent is done two
-  ways as described in `t-utils-test-indent'.  If LANG-FILE is not provided,
-  loop comparing all ./test-LANGUAGE-ts-mode-indent-files/NAME.lang files.
+  ways as described in `t-utils-test-indent'.  This loops
+  on all ./test-LANGUAGE-ts-mode-indent-files/NAME.lang files.
 
   To add a test, create
     ./test-LANGUAGE-ts-mode-indent-files/NAME.lang
@@ -751,29 +743,12 @@ where test-LANGUAGE-ts-mode-indent.el contains:
   after validating it, rename it to
     ./test-LANGUAGE-ts-mode-indent-files/NAME_expected.lang"
 
-    (let ((test-name "test-LANGUAGE-ts-mode-indent")
-          (LANGUAGE-ts-mode--indent-assert t))
-
-      (when (not (t-utils-is-treesit-available 'LANGUAGE test-name))
-        (cl-return-from test-LANGUAGE-ts-mode-font-lock))
-
-      (let ((lang-files (t-utils-get-files (concat test-name "-files") 
"\\.lang$"
-                                        "_expected\\.lang$" ;; skip our 
*_expected.lang baselines
-                                        lang-file))
-            (line-manipulator (lambda ()
-                                ;; Workaround
-                                ;; 
https://github.com/acristoffers/tree-sitter-LANGUAGE/issues/32
-                                (goto-char (point-min))
-                                (while (not (eobp))
-                                  (let* ((node   (treesit-node-at (point)))
-                                         (parent (and node 
(treesit-node-parent node))))
-                                    (when (string= (treesit-node-type parent) 
"ERROR")
-                                      (insert " ")))
-                                  (forward-line)))))
-
-        (t-utils-test-indent test-name lang-files line-manipulator)))
-    ;; return "success" for M-: (test-LANGUAGE-ts-mode-font-lock)
-    "success")
+    (let ((test-name "test-LANGUAGE-ts-mode-indent"))
+      (when (t-utils-is-treesit-available 'LANGUAGE test-name)
+        (let ((lang-files (t-utils-get-files (concat test-name "-files") 
"\\.lang\\'"
+                                          "_expected\\.lang\\'" ;; skip our 
*_expected.lang baselines
+                                          test-LANGUAGE-ts-mode-indent--file)))
+          (t-utils-test-indent test-name lang-files)))))
 
 #+end_src
 
@@ -814,7 +789,7 @@ directory recursively.
    large number of LANGUAGE files has good probablity of hitting this. If 
parent doesn't have a
    previous sibling, we'll get "error (void-function stirng-match-p)."
 
-Here's our sweep test:
+Our indent sweep test:
 
 #+begin_src emacs-lisp
   (require 't-utils)
@@ -1073,22 +1048,25 @@ This is good practice because these are fundamental to 
Emacs.
 We follow a similar pattern for writing syntax table tests.
 
 #+begin_src emacs-lisp
-  ;;; test-LANGUAGE-ts-mode-syntax-table.el --- -*- lexical-binding: t -*-
-
-  ;;; Commentary:
-
-  ;;; Code:
-
   (require 't-utils)
   (require 'LANGUAGE-ts-mode)
 
-  (cl-defun test-LANGUAGE-ts-mode-syntax-table (&optional lang-file)
+  (defvar test-LANGUAGE-ts-mode-syntax-table--file nil)
+
+  (defun test-LANGUAGE-ts-mode-syntax-table--file (lang-file)
+    "Test an individual LANG-FILE.
+  This is provided for debugging.
+    M-: (test-LANGUAGE-ts-mode-syntax-table--file 
\"test-LANGUAGE-ts-mode-syntax-table-files/LANG-FILE\")"
+    (let ((test-LANGUAGE-ts-mode-syntax-table--file lang-file))
+      (ert-run-tests-interactively "test-LANGUAGE-ts-mode-syntax-table")))
+
+  (ert-deftest test-LANGUAGE-ts-mode-syntax-table ()
     "Test syntax-table using 
./test-LANGUAGE-ts-mode-syntax-table-files/NAME.lang.
   Compare ./test-LANGUAGE-ts-mode-syntax-table-files/NAME.lang against
   ./test-LANGUAGE-ts-mode-syntax-table-files/NAME_expected.txt, where
-  NAME_expected.txt gives the `syntax-ppss` value of each character in
-  NAME.lang.  If LANG-FILE is not provided, loop comparing all
-  ./test-LANGUAGE-ts-mode-indent-files/NAME.lang files.
+  NAME_expected.txt gives the `syntax-ppss' value of each character in
+  NAME.lang.  This loops on all 
./test-LANGUAGE-ts-mode-syntax-table-files/NAME.lang
+  files.
 
   To add a test, create
     ./test-LANGUAGE-ts-mode-syntax-table-files/NAME.lang
@@ -1098,18 +1076,10 @@ We follow a similar pattern for writing syntax table 
tests.
     ./test-LANGUAGE-ts-mode-syntax-table-files/NAME_expected.lang"
 
     (let ((test-name "test-LANGUAGE-ts-mode-syntax-table"))
-      (when (not (t-utils-is-treesit-available 'LANGUAGE test-name))
-        (cl-return-from test-LANGUAGE-ts-mode-syntax-table))
-
-      (let ((lang-files (t-utils-get-files (concat test-name "-files") 
"\\.lang$" nil lang-file)))
-        (t-utils-test-syntax-table test-name lang-files)))
-
-    ;; return "success" for M-: (test-LANGUAGE-ts-mode-font-lock)
-    "success")
-
-  (provide 'test-LANGUAGE-ts-mode-syntax-table)
-  ;;; test-LANGUAGE-ts-mode-syntax-table.el ends here
-
+      (when (t-utils-is-treesit-available 'LANGUAGE test-name)
+        (let ((lang-files (t-utils-get-files (concat test-name "-files") 
"\\.lang\\'" nil
+                                          
test-LANGUAGE-ts-mode-syntax-table--file)))
+          (t-utils-test-syntax-table test-name lang-files)))))
 #+end_src
 
 * Setup: treesit-thing-settings
@@ -1456,31 +1426,36 @@ where =tests/test-LANUGAGE-ts-mode-show-paren.el= 
contains:
   (require 't-utils)
   (require 'LANGUAGE-ts-mode)
 
-  (cl-defun test-LANGUAGE-ts-mode-show-paren (&optional lang-file)
-    "Test defun movement using 
./test-LANGUAGE-ts-mode-show-paren-files/NAME.EXT.
-  Using ./test-LANGUAGE-ts-mode-show-paren-files/NAME.EXT, compare defun
-  movement against
+  (defvar test-LANGUAGE-ts-mode-show-paren--file nil)
+
+  (defun test-LANGUAGE-ts-mode-show-paren--file (lang-file)
+    "Test an individual LANG-FILE.
+  This is provided for debugging.
+    M-: (test-LANGUAGE-ts-mode-show-paren--file 
\"test-LANGUAGE-ts-mode-show-paren-files/LANG-FILE\")"
+    (let ((test-LANGUAGE-ts-mode-show-paren--file lang-file))
+      (ert-run-tests-interactively "test-LANGUAGE-ts-mode-show-paren")))
+
+  (ert-deftest test-LANGUAGE-ts-mode-show-paren ()
+    "Test show paren mode using 
./test-LANGUAGE-ts-mode-show-paren-files/NAME.lang.
+  Using ./test-LANGUAGE-ts-mode-show-paren-files/NAME.lang, result of
+  `LANGUAGE-ts-mode--show-paren-or-block' for `show-paren-mode' against
   ./test-LANGUAGE-ts-mode-show-paren-files/NAME_expected.org.  If LANG-FILE is
   not provided, loop comparing all
-  ./test-LANGUAGE-ts-mode-show-paren-files/NAME.EXT files.
+  ./test-LANGUAGE-ts-mode-show-paren-files/NAME.lang files.
 
   To add a test, create
-    ./test-LANGUAGE-ts-mode-show-paren-files/NAME.EXT
+    ./test-LANGUAGE-ts-mode-show-paren-files/NAME.lang
   and run this function.  The baseline is saved for you as
     ./test-LANGUAGE-ts-mode-show-paren-files/NAME_expected.org~
   after validating it, rename it to
     ./test-LANGUAGE-ts-mode-show-paren-files/NAME_expected.org"
 
     (let ((test-name "test-LANGUAGE-ts-mode-show-paren"))
+      (when (t-utils-is-treesit-available 'LANGUAGE test-name)
 
-      (when (not (t-utils-is-treesit-available 'LANGUAGE test-name))
-        (cl-return-from test-LANGUAGE-ts-mode-font-lock))
-
-      (let ((lang-files (t-utils-get-files (concat test-name "-files") 
"\\.EXT$" nil lang-file)))
-        (t-utils-test-xr test-name lang-files)))
-      "success")
-
-  (provide 'test-LANGUAGE-ts-mode-show-paren)
+        (let ((lang-files (t-utils-get-files (concat test-name "-files") 
"\\.lang\\'" nil
+                                          
test-LANGUAGE-ts-mode-show-paren--file)))
+          (t-utils-test-xr test-name lang-files)))))
 #+end_src
 
 Each =tests/test-LANUGAGE-ts-mode-show-paren-files/show_paren_ITEM.EXT= file 
looks like the
@@ -1587,395 +1562,11 @@ well worth writing a tree-sitter mode.
 
 * Appendix: t-utils.el
 
-#+begin_src emacs-lisp
-  ;;; t-utils.el --- Test utilities -*- lexical-binding: t -*-
-  ;;
-  ;; Copyright 2025 Free Software Foundation, Inc.
-  ;;
-  ;; This program is free software; you can redistribute it and/or modify
-  ;; it under the terms of the GNU General Public License as published by
-  ;; the Free Software Foundation; either version 3, or (at your option)
-  ;; any later version.
-  ;;
-  ;; This program is distributed in the hope that it will be useful,
-  ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-  ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  ;; GNU General Public License for more details.
-  ;;
-  ;; You should have received a copy of the GNU General Public License
-  ;; along with GNU Emacs; see the file COPYING.  If not, write to
-  ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-  ;;
-
-  ;;; Commentary:
-  ;;
-  ;; Test utilities used by test-*.el files.
-  ;;
+See [[file:../tests/t-utils.el]]. For now copy this to your repository.  It 
would be nice to integrate
+t-utils.el into the Emacs ert package, perhaps ert-ts.el? Alternatively, we 
could create a separate
+ELPA package for it?
 
-  ;;; Code:
-
-  (require 'cl-seq)
-
-  ;; Add abs-path of ".." to load-path so we can require packages from above 
us.
-  (let* ((lf (or load-file-name (buffer-file-name (current-buffer))))
-         (d1 (file-name-directory lf))
-         (parent-dir (expand-file-name (file-name-directory 
(directory-file-name d1)))))
-    (add-to-list 'load-path parent-dir t))
-
-  (defun t-utils-trim ()
-    "Trim trailing whitespace and lines with utf-8-unix encoding."
-    (setq buffer-file-coding-system 'utf-8-unix)
-    (let ((delete-trailing-lines t))
-      (delete-trailing-whitespace (point-min) (point-max))))
-
-  (defun t-utils-get-files (subdir base-regexp &optional skip-regexp 
file-to-use)
-    "Return list of full paths, /path/to/SUBDIR/FILE.
-  The FILE basenames returned match BASE-REGEXP.
-  Files matching optional SKIP-REGEXP are ignored.
-  Optional FILE-TO-USE narrow the list of full paths to that file
-  and the result is a list of one file.
-
-  For example,
-    (t-utils-get-files \"test-LANGUAGE-ts-mode-files\"
-                       \"*\\.lang$\" \"_expected\\.lang$\" file-to-use)
-  will return a list of /path/to/test-NAME/*.lang files, skipping
-  all *_expected.lang files when file-to-use is nil."
-
-    (let ((files (cl-delete-if (lambda (file)
-                                 (and skip-regexp
-                                      (string-match skip-regexp file)))
-                               (directory-files subdir t base-regexp))))
-      (when file-to-use
-        (let ((true-file-to-use (file-truename file-to-use)))
-          (when (not (member true-file-to-use files))
-            (if (file-exists-p true-file-to-use)
-                (error "File %s, resolved to %s, is not a valid selection.
-  It should be one of %S" file-to-use true-file-to-use files)
-              (error "File %s does not exist" file-to-use)))
-          (setq files (list true-file-to-use))))
-      files))
-
-  (defun t-utils-is-treesit-available (language test-name)
-    "Is tree-sitter ready for LANGUAGE?
-  If not available a message saying skipping TEST-NAME is displayed."
-    (let ((available (and (>= emacs-major-version 30) ;; treesit package comes 
with Emacs 30
-                          (progn
-                            (require 'treesit)
-                            (when (fboundp 'treesit-ready-p)
-                              (treesit-ready-p language t))))))
-      (when (not available)
-        (message "skipping-test: %s - %S tree sitter not available." test-name 
language))
-      available))
-
-  (defun t-utils-run (&optional match)
-    "Run test files in current directory matching regexp, MATCH.
-  If optional MATCH is non-nil, only run test file names whose
-  non-directory part matches the regexp, MATCH.  For example,
-  \"^test-foo.*\\\\.el$\" would run tell t-run to run \"test-foo*.el$\"
-  files.  The default MATCH is \"^test-.*\\\\.el$\""
-    (when (not match)
-      (setq match "^test-.*\\.el$"))
-
-    (dolist (test-file (directory-files "." t match))
-      (when (not (load-file test-file))
-        (error "Failed to load %s" test-file))
-      (let ((test-fun (intern
-                       (replace-regexp-in-string "\\.el" "" 
(file-name-nondirectory test-file)))))
-        (funcall test-fun))))
-
-  (defun t-utils--took (start-time)
-    "Return \"- took N seconds\".
-  N is `current-time' minus START-TIME."
-    (format "- took %.2f seconds" (float-time (time-subtract (current-time) 
start-time))))
-
-  (defun t-utils-test-font-lock (test-name lang-files code-to-face)
-    "Test font-lock using on each lang-file in LANG-FILES list.
-  Foreach file in LANG-FILES compare the file against NAME_expected.txt, where
-  NAME the file name minus the extension.  NAME_expected.txt is of same
-  length as the file and has a character for each face setup by font-lock.
-  CODE_TO_FACE is an alist where each elment is (CHAR . FACE).
-  TEST-NAME is used when displaying messages.
-
-  If NAME_expected.txt does not exists or doesn't match the results we
-  got, a NAME_expected.txt~ will be generated.  After reviewing
-  NAME_expected.txt~, you should rename it to NAME_expected.txt or fix
-  your code and rerun the test.
-
-  For example, suppose our LANG-FILE contains
-      int foo(void) {
-          return 1;
-      }
-  our NAME_expected.txt will contain:
-      kkk fffDkkkkD b
-          kkkkkk nD
-      D
-  where int and void are keywords, etc. and CODE-TO-FACE contains:
-    \\='((\"b\" . font-lock-bracket-face)
-      (\"d\" . default)
-      (\"D\" . font-lock-delimiter-face)
-      (\"f\" . font-lock-function-name-face)
-      (\"k\" . font-lock-keyword-face)
-      (\"n\" . font-lock-constant-face))"
-
-    (let ((face-to-code (mapcar (lambda (pair)
-                                  (cons (cdr pair) (car pair)))
-                                code-to-face)))
-      (dolist (lang-file lang-files)
-        (save-excursion
-          (let ((start-time (current-time)))
-            (message "START: %s %s" test-name lang-file)
-
-            (when (boundp 'treesit-font-lock-level)
-              (setq treesit-font-lock-level 4))
-
-            (find-file lang-file)
-
-            ;; Force font lock to throw catchable errors.
-            (font-lock-mode 1)
-            (font-lock-flush (point-min) (point-max))
-            (font-lock-ensure (point-min) (point-max))
-
-            (goto-char (point-min))
-            (let* ((got "")
-                   (expected-file (replace-regexp-in-string "\\.[^.]+$" 
"_expected.txt"
-                                                            lang-file))
-                   (got-file (concat expected-file "~"))
-                   (expected (when (file-exists-p expected-file)
-                               (with-temp-buffer
-                                 (insert-file-contents-literally expected-file)
-                                 (buffer-string)))))
-              (while (not (eobp))
-                (let* ((face (if (face-at-point) (face-at-point) 'default))
-                       (code (if (looking-at "\\([ \t\n]\\)")
-                                 (match-string 1)
-                               (cdr (assoc face face-to-code)))))
-                  (when (not code)
-                    (error "Face, %S, is not in code-to-face alist" face))
-                  (setq got (concat got code))
-                  (forward-char)
-                  (when (looking-at "\n")
-                    (setq got (concat got "\n"))
-                    (forward-char))))
-
-              (when (not (string= got expected))
-                (let ((coding-system-for-write 'raw-text-unix))
-                  (write-region got nil got-file))
-                (when (not expected)
-                  (error "Baseline for %s does not exists.  \
-  See %s and if it looks good rename it to %s"
-                         lang-file got-file expected-file))
-                (when (= (length got) (length expected))
-                  (let* ((diff-idx (1- (compare-strings got nil nil expected 
nil nil)))
-                         (got-code (substring got diff-idx (1+ diff-idx)))
-                         (got-face (cdr (assoc got-code code-to-face)))
-                         (expected-code (substring expected diff-idx (1+ 
diff-idx)))
-                         (expected-face (cdr (assoc expected-code 
code-to-face))))
-                    (error "Baseline for %s does not match, got: %s, expected: 
%s.  \
-  Difference at column %d: got code-to-face (\"%s\" . %S), expected 
code-to-face (\"%s\" . %S)"
-                           lang-file got-file expected-file
-                           diff-idx
-                           got-code got-face
-                           expected-code expected-face)))
-                (error "Baseline for %s does not match, lengths are different, 
got: %s, expected: %s"
-                       lang-file got-file expected-file))
-              (kill-buffer))
-            (message "PASS: %s %s %s" test-name lang-file (t-utils--took 
start-time)))))))
-
-  (defun t-utils--test-indent-typing (lang-file lang-file-mode
-                                                expected expected-file
-                                                &optional line-manipulator)
-    "Exercise indent by simulating the creation of LANG-FILE via typing.
-  This compares the simulation of typing LANG-FILE against the
-  EXPECTED content in EXPECTED-FILE
-
-  The typing occurs in a buffer named \"typing__NAME.EXT\" where NAME.EXT
-  is the basename of LANG-FILE.
-
-  The typing buffer is initialized with the string-trim'd version of the
-  non-empty lines of LANG-FILE.  If optional LINE-MANIPULATOR function is
-  specified, it is called with the typing buffer as the current
-  buffer.  LINE-MANIPULATOR should only adjust whitespace in the lines.  It
-  should not add newlines to the buffer.  LINE-MANIPULATOR is called from
-  within a `save-excursion', so your function doesn't need to do that.
-
-  After initializating the typing buffer, it's mode is set to
-  LANG-FILE-MODE.  Each line is then indented via `indent-for-tab-command'
-  and blank lines are inserted by calling `newline'.`"
-
-    (let* ((typing-lang-file-name (concat "typing__" (file-name-nondirectory 
lang-file)))
-           (contents (with-temp-buffer
-                       (insert-file-contents-literally lang-file)
-                       (buffer-substring (point-min) (point-max))))
-           (lines (split-string (string-trim contents) "\n")))
-      (with-current-buffer (get-buffer-create typing-lang-file-name)
-        (erase-buffer)
-        (funcall lang-file-mode)
-
-        ;; Insert the non-empty lines into typing-lang-file-name buffer
-        (dolist (line lines)
-          (setq line (string-trim line))
-          (when (not (string= line ""))
-            (insert line "\n")))
-
-        (goto-char (point-min))
-
-        (when line-manipulator
-          (save-excursion
-            (funcall line-manipulator)))
-
-        ;; Now indent each line and insert the empty ("") lines into 
typing-lang-file-buffer
-        ;; as we indent. This exercises the RET and TAB behaviors which cause 
different
-        ;; tree-sitter nodes to be provided to the indent engine rules.
-        (while (not (eobp))
-
-          (call-interactively #'indent-for-tab-command) ;; TAB on code just 
added
-
-          ;; While next line in our original contents is a newline insert "\n"
-          (while (let ((next-line (nth (line-number-at-pos (point)) lines)))
-                   (and next-line (string-match-p "^[ \t\r]*$" next-line)))
-            (goto-char (line-end-position))
-            ;; RET to add blank line
-            (call-interactively #'newline)
-            ;; TAB on the same blank line can result in different tree-sitter 
nodes than
-            ;; the RET, so exercise that.
-            (call-interactively #'indent-for-tab-command))
-          (forward-line))
-
-        (t-utils-trim)
-
-        (let ((typing-got (buffer-substring (point-min) (point-max))))
-          (set-buffer-modified-p nil)
-          (kill-buffer)
-          (when (not (string= typing-got expected))
-            (let ((coding-system-for-write 'raw-text-unix)
-                  (typing-got-file (replace-regexp-in-string "\\.\\([^.]+\\)$"
-                                                             "_typing.\\1~"
-                                                             lang-file)))
-              (write-region typing-got nil typing-got-file)
-              (error "Typing %s line-by-line does not match %s, we got %s" 
lang-file expected-file
-                     typing-got-file)))))))
-
-  (defun t-utils-test-indent (test-name lang-files &optional line-manipulator)
-    "Test indent on each file in LANG-FILES list.
-  Compare indent of each NAME.EXT in LANG-FILES against NAME_expected.EXT.
-  TEST-NAME is used in messages.
-
-  If NAME_expected.EXT does not exist or the indent of NAME.EXT doesn't
-  match NAME_expected.txt, NAME_expected.EXT~ will be created.  You are
-  then instructured to validate the indent and rename NAME_expected.EXT~
-  to NAME_expected.EXT.
-
-  To add a test for TEST-NAME.el, in it's corresponding TEST-NAME-files/
-  directory, create TEST-NAME-files/NAME.EXT, then run the test.  Follow
-  the messages to accept the generated baseline after validating it.
-
-  Two methods are used to indent each file in LANG-FILES,
-   1. (indent-region (point-min) (point-man))
-   2. Simulation of typing lang-file to exercise TAB and RET,
-      see `t-utils--test-indent-typing'.  In tree-sitter modes, TAB and RET
-      need to be handled and this verifies they are handled.
-
-  See `t-utils--test-indent-type' for LINE-MANIPULATOR."
-
-    (dolist (lang-file lang-files)
-      (let* ((expected-file (replace-regexp-in-string "\\.\\([^.]+\\)$" 
"_expected.\\1" lang-file))
-             (expected (when (file-exists-p expected-file)
-                         (with-temp-buffer
-                           (insert-file-contents-literally expected-file)
-                           (buffer-string))))
-             lang-file-major-mode)
-
-        ;; Indent lang-file
-        (save-excursion
-          (let ((start-time (current-time)))
-            (message "START: %s <indent-region> %s" test-name lang-file)
-            (find-file lang-file)
-            (setq lang-file-major-mode major-mode)
-            (indent-region (point-min) (point-max))
-            (t-utils-trim)
-            (let ((got (buffer-substring (point-min) (point-max)))
-                  (got-file (concat expected-file "~")))
-              (set-buffer-modified-p nil)
-              (kill-buffer)
-              (when (not (string= got expected))
-                (let ((coding-system-for-write 'raw-text-unix))
-                  (write-region got nil got-file))
-                (when (not expected)
-                  (error "Baseline for %s does not exists - if %s looks good 
rename it to %s"
-                         lang-file got-file expected-file))
-                (error "Baseline for %s does not match, got: %s, expected: %s"
-                       lang-file got-file expected-file)))
-            (message "PASS: %s <indent-region> %s %s" test-name lang-file
-                     (t-utils--took start-time))))
-
-        ;; Now, simulate typing lang-file and indent it (exercise TAB and RET)
-        (let ((start-time (current-time)))
-          (message "START: %s <indent-via-typing> %s" test-name lang-file)
-          (t-utils--test-indent-typing lang-file lang-file-major-mode
-                                       expected expected-file
-                                       line-manipulator)
-          (message "PASS: %s <indent-via-typing> %s %s" test-name lang-file
-                   (t-utils--took start-time))))))
-
-  (defun t-utils-test-syntax-table (test-name lang-files)
-    "Test syntax-table on each file in LANG-FILES list.
-  Compare syntax-table of each NAME.EXT in LANG-FILES against 
NAME_expected.txt.
-  TEST-NAME is used in messages.
-
-  If NAME_expected.txt does not exist or the syntax-table of NAME.txt doesn't
-  match NAME_expected.txt, NAME_expected.txt~ will be created.  You are
-  then instructured to validate the syntax-table and rename NAME_expected.txt~
-  to NAME_expected.txt.
-
-  To add a test for TEST-NAME.el, in it's corresponding TEST-NAME-files/
-  directory, create TEST-NAME-files/NAME.EXT, then run the test.  Follow
-  the messages to accept the generated baseline after validating it."
-
-    (dolist (lang-file lang-files)
-      (save-excursion
-        (let ((start-time (current-time)))
-          (message "START: %s %s" test-name lang-file)
-
-          (find-file lang-file)
-          (goto-char (point-min))
-
-          (let* ((got "")
-                 (expected-file (replace-regexp-in-string "\\.[^.]+$" 
"_expected.txt" lang-file))
-                 (got-file (concat expected-file "~"))
-                 (expected (when (file-exists-p expected-file)
-                             (with-temp-buffer
-                               (insert-file-contents-literally expected-file)
-                               (buffer-string)))))
-            (while (not (eobp))
-              (when (looking-at "^")
-                (setq got (concat got (format "Line:%d: %s\n"
-                                              (line-number-at-pos)
-                                              (buffer-substring-no-properties 
(point)
-                                                                              
(line-end-position))))))
-
-              (let ((char (buffer-substring-no-properties (point) (1+ 
(point)))))
-                (when (string= char "\n")
-                  (setq char "\\n"))
-                (setq got (concat got (format "  %2s: %S\n" char (syntax-ppss 
(point))))))
-
-              (forward-char))
-
-            (when (not (string= got expected))
-              (let ((coding-system-for-write 'raw-text-unix))
-                (write-region got nil got-file))
-              (when (not expected)
-                (error "Baseline for %s does not exists.  \
-  See %s and if it looks good rename it to %s"
-                       lang-file got-file expected-file))
-              (error "Baseline for %s does not match, got: %s, expected: %s"
-                     lang-file got-file expected-file))
-            (kill-buffer))
-          (message "PASS: %s %s %s" test-name lang-file (t-utils--took 
start-time))))))
-
-  (provide 't-utils)
-  ;;; t-utils.el ends here
-
-#+end_src
+TODO extract help from t-utils.el and place here.
 
 * Issues
 
diff --git a/matlab-ts-mode.el b/matlab-ts-mode.el
index 4d65a5781c..ebd90d38a8 100644
--- a/matlab-ts-mode.el
+++ b/matlab-ts-mode.el
@@ -1336,6 +1336,7 @@ Enable/disable `matlab-sections-minor-mode' based on file 
content."
 ;;; Electric Pair Mode, M-x electric-pair-mode
 
 (declare-function electric-pair-default-inhibit "elec-pair")
+
 (defun matlab-ts-mode--electric-pair-inhibit-predicate (char)
   "Return non-nil if `electric-pair-mode' should not pair this CHAR.
 Do not pair the transpose operator, (\\='), but pair it when used as a
@@ -1362,8 +1363,14 @@ single quote string."
 
        ;; Case: string delimiter
        ;;    double up if starting a new string => return nil
-       ((string= "'" type-back1)
-        (not (string= "string" (treesit-node-type (treesit-node-parent 
node-back1)))))
+       ((string= "'" type-back1 )
+        (let ((parent-back1-type (treesit-node-type (treesit-node-parent 
node-back1))))
+          ;; When we type
+          ;;   s = '
+          ;; we'll get a syntax error from the parse-tree.  Older versions of 
the
+          ;; matlab tree-sitter would return string so we keep that condition.
+          (not (or (string= "ERROR" parent-back1-type)
+                   (string= "string" parent-back1-type)))))
 
        ;; Case: inside a single quote string
        ;;    s = 'foobar'
diff --git a/tests/metest.el b/tests/metest.el
index db67edc7a2..d0c1fc4b1d 100644
--- a/tests/metest.el
+++ b/tests/metest.el
@@ -83,7 +83,7 @@
   (when (not (eq system-type 'windows-nt))
     (metest-fill-paragraph))
 
-  ;; test-*.el
+  ;; Run test-*.el. t-utils-run must be last because it will exit emacs when 
noninteractive.
   (when (>= emacs-major-version 30) ;; TODO - should we eliminate this version 
check?
     (t-utils-run)))
 
diff --git a/tests/t-utils.el b/tests/t-utils.el
index 0cebd2b1d5..517c86f66d 100644
--- a/tests/t-utils.el
+++ b/tests/t-utils.el
@@ -21,12 +21,25 @@
 ;;
 ;; Test utilities used by test-*.el files.
 ;;
+;; t-utils.el uses the ert package.  Many of t-utils functions operate on a 
set of input files and
+;; compare them against baselines.  For example, `t-utils-test-font-lock' 
loops over a set of files,
+;; NAME.EXT, and compares them against NAME_expected.EXT.  The ert package 
does not provide a
+;; looping facility.  Therefore, t-utils internally performs the looping.  
This makes reporting a
+;; little off.  One test is really a number of tests defined by the test input 
files.  To debug a
+;; specifice input file, the caller of the t-utils needs to setup for 
debugging.  See
+;; `t-utils-test-font-lock' below for this setup.
+;;
+;; Tip: type \"m\" on the colored dots in the *ert* buffer to see the messages 
for that ert test
+;; and the messages contain the sub-tests from the test loop for that ert test.
+;;
+
 
 ;;; Code:
 
 (require 'cl-macs)
 (require 'cl-seq)
 (require 'diff)
+(require 'ert)
 (require 'outline)
 (require 'treesit)
 
@@ -51,7 +64,7 @@ and the result is a list of one file.
 
 For example,
   (t-utils-get-files \"test-LANGUAGE-ts-mode-files\"
-                     \"*\\.lang$\" \"_expected\\.lang$\" file-to-use)
+                     \"\\\\.lang\\\\\\='\" \"_expected\\\\.lang\\\\\\='\" 
file-to-use)
 will return a list of /path/to/test-NAME/*.lang files, skipping
 all *_expected.lang files when file-to-use is nil."
 
@@ -71,7 +84,8 @@ It should be one of %S" file-to-use true-file-to-use files)
 
 (defun t-utils-is-treesit-available (language test-name)
   "Is tree-sitter ready for LANGUAGE?
-If not available a message saying skipping TEST-NAME is displayed."
+If not available a message saying skipping TEST-NAME is displayed
+and nil is returned."
   (let ((available (and (>= emacs-major-version 30) ;; treesit package comes 
with Emacs 30
                         (progn
                           (require 'treesit)
@@ -85,21 +99,84 @@ If not available a message saying skipping TEST-NAME is 
displayed."
   "Run test files in current directory matching regexp, MATCH.
 If optional MATCH is non-nil, only run test file names whose
 non-directory part matches the regexp, MATCH.  For example,
-\"^test-foo.*\\\\.el$\" would run tell t-run to run \"test-foo*.el$\"
-files.  The default MATCH is \"^test-.*\\\\.el$\""
+\"^test-foo.*\\\\.el\\\\\\='\" would run tell t-utils-run to run
+\"test-foo*.el\" files.  The default MATCH is
+\"^test-.*\\\\.el\\\\\\='\".
+
+It is assumed each matched test contains `ert-deftest' that has the same
+name as the test file.  These test names are then run using `ert'."
+
   (when (not match)
-    (setq match "^test-.*\\.el$"))
+    (setq match "^test-.*\\.el\\'"))
 
-  (dolist (test-file (directory-files "." t match))
-    (when (not (load-file test-file))
-      (error "Failed to load %s" test-file))
-    (let ((test-fun (intern
-                     (replace-regexp-in-string "\\.el" "" 
(file-name-nondirectory test-file)))))
-      (funcall test-fun))))
+  (let ((tests '()))
+    
+    (dolist (test-file (directory-files "." t match))
+      (when (not (load-file test-file))
+        (error "Failed to load %s" test-file))
+      (push (replace-regexp-in-string "\\.el" "" (file-name-nondirectory 
test-file)) tests))
+
+    (let ((test-selector (rx-to-string `(seq bos (or ,@tests) eos))))
+      (if noninteractive
+          (ert-run-tests-batch-and-exit test-selector)
+        (ert-run-tests-interactively test-selector)))))
 
 (defvar-local t-utils--buf-file nil
   "Name of file associated with t-utils temporary buffers.")
 
+(defun t-utils--took (start-time)
+  "Return \"- took N seconds\".
+N is `current-time' minus START-TIME."
+  (format "- took %.2f seconds" (float-time (time-subtract (current-time) 
start-time))))
+
+(defun t-utils--baseline-check (test-name start-time
+                                          lang-file got got-file expected 
expected-file
+                                          &optional checker-fun)
+  "Validate GOT string matches EXPECTED for LANG-FILE of TEST-NAME.
+GOT-FILE is equal to EXPECTED-FILE with a tilde prefix.  GOT-FILE will
+be created if (string= GOT EXPECTED) is nil.  EXPECTED-FILE is the
+baseline file for EXPECTED.  START-TIME is when we started the test and
+is used in displaying the test took time.
+
+Optional CHECKER-FUN if specified is called with LANG-FILE GOT GOT-FILE
+EXPECTED EXPECTED-FILE and can return a specialized error message or
+nil to use the standard error message.
+
+Returns nil on success, otherwise an error message list of strings if
+baseline check fails."
+
+  (let (error-msg)
+    (when (not (string= got expected))
+      (let ((coding-system-for-write 'raw-text-unix))
+        (write-region got nil got-file))
+
+      (when checker-fun
+        (setq error-msg (funcall checker-fun lang-file got got-file expected 
expected-file)))
+
+      (when (not error-msg)
+        (if (not expected)
+            (setq error-msg (list
+                             (format "Baseline for %s does not exists." 
lang-file)
+                             (format "Got: %s" got-file)
+                             (format "If got looks good, rename it to: %s" 
expected-file)))
+          (setq error-msg (list
+                           (format "Baseline for %s does not match expected." 
lang-file)
+                           (format "Got: %s" got-file )
+                           (format "Expected: %s" expected-file))))))
+    ;; When run noninteractively, having errors show up like compiler messages 
aids in finding
+    ;; them. For example, run the test and pipe to a log file, then view the 
log file in
+    ;; `compilation-minor-mode'.
+    (when error-msg
+      (message "%s:1: error: test failed" lang-file)
+      (dolist (msg error-msg)
+        (message "-> %s" msg)))
+
+    ;; Report the status of the test.
+    (message "%s: %s %s %s"
+             (if error-msg "FAIL" "PASS")
+             test-name lang-file (t-utils--took start-time))
+    error-msg))
+
 (defun t-utils--insert-file-for-test (file &optional file-major-mode)
   "Insert FILE into current temporary buffer for testing.
 If optional FILE-MAJOR-MODE function is provided, run that, otherwise"
@@ -124,11 +201,6 @@ If optional FILE-MAJOR-MODE function is provided, run 
that, otherwise"
   ;; Stash away the real buffer file for later use (and return it).
   (setq-local t-utils--buf-file file))
 
-(defun t-utils--took (start-time)
-  "Return \"- took N seconds\".
-N is `current-time' minus START-TIME."
-  (format "- took %.2f seconds" (float-time (time-subtract (current-time) 
start-time))))
-
 (defun t-utils--get-buf-file ()
   "Return the file corresponding to the buffer under test."
   (cond ((and (local-variable-if-set-p 't-utils--buf-file)
@@ -198,7 +270,7 @@ Returns diff of START-CONTENTS and END-CONTENTS."
 Verify that diff is setup correctly, check `diff-command', etc.
 You can run `t-utils--diff-check' to debug"))))
 
-(defun t-utils-diff-strings (start-contents end-contents)
+(defun t-utils--diff-strings (start-contents end-contents)
   "Return diff of START-CONTENTS and END-CONTENTS."
 
   ;; Do a one time diff on sample start/end contents vs expected result
@@ -316,7 +388,7 @@ You can run `t-utils--diff-check' to debug"))))
                   (setq result (concat result
                                        "  Buffer modified:\n"
                                        "  #+begin_src diff\n"
-                                       (t-utils-diff-strings start-contents 
end-contents)
+                                       (t-utils--diff-strings start-contents 
end-contents)
                                        "  #+end_src diff\n")
                         debug-msg (concat debug-msg ", buffer modified")))
 
@@ -406,75 +478,82 @@ my_test.c.  The result is compared against
 test-defun-movement/my_test_expected.org.  If my_test_expected.org does
 not exist or result doesn't match the existing my_test_expected.org,
 my_test_expected.org~ is generated and if it looks correct, you should
-rename it to my_test_expected.org."
+rename it to my_test_expected.org.
 
-  (dolist (lang-file lang-files)
-    (with-temp-buffer
-      (t-utils--insert-file-for-test lang-file)
-      (let* ((start-time (current-time))
-             (expected-file (replace-regexp-in-string "\\.[^.]+$" 
"_expected.org"
-                                                      lang-file))
-             (expected (when (file-exists-p expected-file)
-                         (with-temp-buffer
-                           (insert-file-contents-literally expected-file)
-                           (buffer-string))))
-             (got "#+startup: showall\n")
-             (got-file (concat expected-file "~")))
-
-        (message "START: %s %s" test-name lang-file)
-
-        (while (re-search-forward "(t-utils-xr" nil t)
-          (re-search-backward "(")
-          (forward-list)
-          (let* ((xr-end-point (point)))
-            (setq t-utils--xr-impl-result-active t)
-            (unwind-protect
-                (progn
-                  ;; `eval-last-sexp' on (t-utils-xr COMMANDS) calls
-                  ;; `elisp--eval-last-sexp-print-value' which will (prin1 
value output) where
-                  ;; output is t which means send to echo area.  We don't want 
to print value which
-                  ;; is nil in our case, so we override 
elisp--eval-last-sexp-print-value locally
-                  ;; during this eval.
-                  (advice-add #'elisp--eval-last-sexp-print-value :override
-                              #'t-utils--eval-sexp-print-advice)
-
-                  (eval-last-sexp nil)
-                  (setq got (concat got t-utils--xr-impl-result)
-                        t-utils--xr-impl-result-active nil
-                        t-utils--xr-impl-result nil))
-              (progn
-                (setq t-utils--xr-impl-result-active nil
-                      t-utils--xr-impl-result nil)
-                (advice-remove #'elisp--eval-last-sexp-print-value
-                              #'t-utils--eval-sexp-print-advice)))
-
-            ;; look for next (t-utils-xr COMMANDS)
-            (goto-char xr-end-point)))
+TODO should example test setup, see t-utils-test-font-lock."
 
-        (kill-buffer)
+  (let ((error-msgs '()))
+    (dolist (lang-file lang-files)
+      (with-temp-buffer
+
+        (t-utils--insert-file-for-test lang-file)
+
+        (let* ((start-time (current-time))
+               (expected-file (replace-regexp-in-string "\\.[^.]+\\'" 
"_expected.org"
+                                                        lang-file))
+               (expected (when (file-exists-p expected-file)
+                           (with-temp-buffer
+                             (insert-file-contents-literally expected-file)
+                             (buffer-string))))
+               (got "#+startup: showall\n")
+               (got-file (concat expected-file "~")))
+
+          (message "START: %s %s" test-name lang-file)
+
+          (condition-case err
+              (while (re-search-forward "(t-utils-xr" nil t)
+                (re-search-backward "(")
+                (forward-list)
+                (let* ((xr-end-point (point)))
+                  (setq t-utils--xr-impl-result-active t)
+                  (unwind-protect
+                      (progn
+                        ;; `eval-last-sexp' on (t-utils-xr COMMANDS) calls
+                        ;; `elisp--eval-last-sexp-print-value' which will 
(prin1 value output) where
+                        ;; output is t which means send to echo area.  We 
don't want to print value
+                        ;; which is nil in our case, so we override
+                        ;; elisp--eval-last-sexp-print-value locally during 
this eval.
+                        (advice-add #'elisp--eval-last-sexp-print-value 
:override
+                                    #'t-utils--eval-sexp-print-advice)
+                        
+                        (eval-last-sexp nil)
+                        (setq got (concat got t-utils--xr-impl-result)
+                              t-utils--xr-impl-result-active nil
+                              t-utils--xr-impl-result nil))
+                    (progn
+                      (setq t-utils--xr-impl-result-active nil
+                            t-utils--xr-impl-result nil)
+                      (advice-remove #'elisp--eval-last-sexp-print-value
+                                     #'t-utils--eval-sexp-print-advice)))
+                  
+                  ;; look for next (t-utils-xr COMMANDS)
+                  (goto-char xr-end-point)))
+            (error
+             (error "Failure in %s at point %d: %s" lang-file (point) 
(error-message-string err))
+             ))
+
+          (kill-buffer)
 
-        (when (string= got "")
-          (error "No (t-utils-xr COMMANDS) found in %s" lang-file))
+          (when (string= got "")
+            (error "No (t-utils-xr COMMANDS) found in %s" lang-file))
 
-        (when (not (string= got expected))
-          (let ((coding-system-for-write 'raw-text-unix))
-            (write-region got nil got-file))
-          (when (not expected)
-            (error "Baseline for %s does not exists.  \
-See %s and if it looks good rename it to %s"
-                   lang-file got-file expected-file))
-          (error "Baseline for %s does not match, got: %s, expected: %s"
-                 lang-file got-file expected-file))
+          (let ((error-msg (t-utils--baseline-check test-name start-time
+                                                    lang-file got got-file 
expected expected-file)))
+            (when error-msg
+              (push error-msg error-msgs))))))
 
-        (message "PASS: %s %s %s" test-name lang-file (t-utils--took 
start-time))))))
+    ;; Validate t-utils-test-xr result
+    (setq error-msgs (reverse error-msgs))
+    (should (equal error-msgs '()))))
 
 (defun t-utils-test-font-lock (test-name lang-files code-to-face)
   "Test font-lock using on each lang-file in LANG-FILES list.
-Foreach file in LANG-FILES compare the file against NAME_expected.txt, where
-NAME the file name minus the extension.  NAME_expected.txt is of same
-length as the file and has a character for each face setup by font-lock.
-CODE_TO_FACE is an alist where each elment is (CHAR . FACE).
-TEST-NAME is used when displaying messages.
+Foreach lang-file NAME.EXT in LANG-FILES compare the file against
+NAME_expected.txt, where NAME the file name minus the lang-file
+extension, EXT.  NAME_expected.txt is of same length as the file and has
+a character for each face setup by font-lock.  CODE_TO_FACE is an alist
+where each elment is (CHAR . FACE).  TEST-NAME is used when displaying
+messages.
 
 If NAME_expected.txt does not exists or doesn't match the results we
 got, a NAME_expected.txt~ will be generated.  After reviewing
@@ -497,11 +576,55 @@ where int and void are keywords, etc. and CODE-TO-FACE 
contains:
     (\"k\" . font-lock-keyword-face)
     (\"n\" . font-lock-constant-face))
 
-TODO give example calling test-name.el (and for others)"
+Example test setup:
+
+  ./LANGUAGE-ts-mode.el
+  ./tests/test-LANUGAGE-ts-mode-font-lock.el
+  ./tests/test-LANUGAGE-ts-mode-font-lock-files/NAME1.EXT
+  ./tests/test-LANUGAGE-ts-mode-font-lock-files/NAME1_expected.txt
+  ./tests/test-LANUGAGE-ts-mode-font-lock-files/NAME2.EXT
+  ./tests/test-LANUGAGE-ts-mode-font-lock-files/NAME2_expected.txt
+  ....
+
+Where ./tests/test-LANUGAGE-ts-mode-font-lock.el contains:
+
+  (defvar test-LANGUAGE-ts-mode-font-lock--file nil)
+
+  (defun test-LANGUAGE-ts-mode-font-lock--file (lang-file)
+    \"Test font-lock on LANG-FILE.\"
+    (let ((test-LANGUAGE-ts-mode-font-lock--file lang-file))
+      (ert-run-tests-interactively \"test-LANGUAGE-ts-mode-font-lock\")))
+
+  (ert-deftest test-LANGUAGE-ts-mode-font-lock ()
+
+    (let* ((lang-files (t-utils-get-files
+                        (concat test-name \"-files\")
+                                \"\\.EXT\\\\\\='\" nil
+                                test-LANGUAGE-ts-mode-font-lock--file))
+           (code-to-face \\='(
+                           (\"b\" . font-lock-bracket-face)
+                           (\"B\" . font-lock-builtin-face)
+                           (\"c\" . font-lock-comment-face)
+                           ....
+                           )))
+      (t-utils-test-font-lock test-name lang-files code-to-face)))
+
+To loop over all NAME*.EXT font-lock test files, interactively
+
+  \\[ert] RET test-LANGUAGE-ts-mode-font-lock RET
+
+In the *ert* buffer, you can type \"m\" at the point of the test (where
+the color marker is) to see messages that were displayed by your test.
+
+To debug a specific font-lock test file
+
+ M-: (test-LANGUAGE-ts-mode-font-lock--file \
+\"test-LANUGAGE-ts-mode-font-lock-files/NAME.EXT\")"
 
   (let ((face-to-code (mapcar (lambda (pair)
                                 (cons (cdr pair) (car pair)))
-                              code-to-face)))
+                              code-to-face))
+        (error-msgs '()))
     (dolist (lang-file lang-files)
       (with-temp-buffer
         (t-utils--insert-file-for-test lang-file)
@@ -514,7 +637,7 @@ TODO give example calling test-name.el (and for others)"
           (font-lock-ensure (point-min) (point-max))
 
           (goto-char (point-min))
-          (let* ((expected-file (replace-regexp-in-string "\\.[^.]+$" 
"_expected.txt"
+          (let* ((expected-file (replace-regexp-in-string "\\.[^.]+\\'" 
"_expected.txt"
                                                           lang-file))
                  (expected (when (file-exists-p expected-file)
                              (with-temp-buffer
@@ -538,49 +661,41 @@ TODO give example calling test-name.el (and for others)"
 
             (kill-buffer)
 
-            (when (not (string= got expected))
-              (let ((coding-system-for-write 'raw-text-unix))
-                (write-region got nil got-file))
-              (when (not expected)
-                (error "Baseline for %s does not exists.  \
-See %s and if it looks good rename it to %s"
-                       lang-file got-file expected-file))
-              (when (= (length got) (length expected))
-                (let* ((diff-idx (1- (compare-strings got nil nil expected nil 
nil)))
-                       (got-code (substring got diff-idx (1+ diff-idx)))
-                       (got-face (cdr (assoc got-code code-to-face)))
-                       (expected-code (substring expected diff-idx (1+ 
diff-idx)))
-                       (expected-face (cdr (assoc expected-code 
code-to-face))))
-                  (error "Baseline for %s does not match, got: %s, expected: 
%s.  \
-Difference at column %d: got code-to-face (\"%s\" . %S), expected code-to-face 
(\"%s\" . %S)"
-                         lang-file got-file expected-file
-                         diff-idx
-                         got-code got-face
-                         expected-code expected-face)))
-              (error "Baseline for %s does not match, lengths are different, 
got: %s, expected: %s"
-                     lang-file got-file expected-file)))
-          (message "PASS: %s %s %s" test-name lang-file (t-utils--took 
start-time)))))))
+            (let ((error-msg
+                   (t-utils--baseline-check
+                    test-name start-time
+                    lang-file got got-file expected expected-file
+                    (lambda (lang-file got got-file expected expected-file)
+                      (when (= (length got) (length expected))
+                        (let* ((diff-idx (1- (compare-strings got nil nil 
expected
+                                                              nil nil)))
+                               (got-code (substring got diff-idx (1+ 
diff-idx)))
+                               (got-face (cdr (assoc got-code code-to-face)))
+                               (expected-code (substring expected diff-idx (1+ 
diff-idx)))
+                               (expected-face (cdr (assoc expected-code 
code-to-face))))
+                          (list (format "Baseline for %s does not match" 
lang-file)
+                                (format "Got: %s" got-file)
+                                (format "Expected: %s" expected-file)
+                                (format "Difference at column %d: \
+got code-to-face (\"%s\" . %S), expected code-to-face (\"%s\" . %S)"
+                                        diff-idx
+                                        got-code got-face
+                                        expected-code expected-face))))))))
+              (when error-msg
+                (push error-msg error-msgs)))))))
+    ;; Validate t-utils-test-font-lock result
+    (setq error-msgs (reverse error-msgs))
+    (should (equal error-msgs '()))))
 
 (defun t-utils--test-indent-typing (lang-file lang-file-mode
                                               expected expected-file
                                               &optional line-manipulator)
   "Exercise indent by simulating the creation of LANG-FILE via typing.
 This compares the simulation of typing LANG-FILE against the
-EXPECTED content in EXPECTED-FILE
-
-The typing occurs in a buffer named \"typing__NAME.EXT\" where NAME.EXT
-is the basename of LANG-FILE.
-
-The typing buffer is initialized with the string-trim'd version of the
-non-empty lines of LANG-FILE.  If optional LINE-MANIPULATOR function is
-specified, it is called with the typing buffer as the current
-buffer.  LINE-MANIPULATOR should only adjust whitespace in the lines.  It
-should not add newlines to the buffer.  LINE-MANIPULATOR is called from
-within a `save-excursion', so your function doesn't need to do that.
+EXPECTED content in EXPECTED-FILE.
 
-After initializating the typing buffer, it's mode is set to
-LANG-FILE-MODE.  Each line is then indented via `indent-for-tab-command'
-and blank lines are inserted by calling `newline'.`"
+LANG-FILE-MODE is the mode to use for LANG-FILE.  See
+See `t-utils-test-indent' for LINE-MANIPULATOR."
 
   (let* ((typing-lang-file-name (concat "typing__" (file-name-nondirectory 
lang-file)))
          (contents (with-temp-buffer
@@ -623,17 +738,22 @@ and blank lines are inserted by calling `newline'.`"
 
       (t-utils--trim)
 
-      (let ((typing-got (buffer-substring (point-min) (point-max))))
+      (let ((typing-got (buffer-substring (point-min) (point-max)))
+            error-msg)
         (set-buffer-modified-p nil)
         (kill-buffer)
         (when (not (string= typing-got expected))
           (let ((coding-system-for-write 'raw-text-unix)
-                (typing-got-file (replace-regexp-in-string "\\.\\([^.]+\\)$"
+                (typing-got-file (replace-regexp-in-string "\\.\\([^.]+\\)\\'"
                                                            "_typing.\\1~"
                                                            lang-file)))
             (write-region typing-got nil typing-got-file)
-            (error "Typing %s line-by-line does not match %s, we got %s" 
lang-file expected-file
-                   typing-got-file)))))))
+            (setq error-msg
+                  (list
+                   (format "Typing %s line-by-line does not match %s" 
lang-file expected-file)
+                   (format "Got: %s" typing-got-file)))))
+        ;; result is nil or an error message list of strings
+        error-msg))))
 
 (defun t-utils-test-indent (test-name lang-files &optional line-manipulator 
error-nodes-regexp)
   "Test indent on each file in LANG-FILES list.
@@ -645,12 +765,13 @@ match NAME_expected.txt, NAME_expected.EXT~ will be 
created.  You are
 then instructured to validate the indent and rename NAME_expected.EXT~
 to NAME_expected.EXT.
 
-To add a test for TEST-NAME.el which call this function, in the
+To add a test for TEST-NAME.el which calls this function, in the
 corresponding TEST-NAME-files/ directory, create
 TEST-NAME-files/NAME.EXT, then run the test.  Follow the messages to
 accept the generated baseline after validating it.
 
 Two methods are used to indent each file in LANG-FILES,
+
  1. (indent-region (point-min) (point-man))
 
  2. Indent via typing simulation.  If lang-file has no error nodes in the
@@ -658,59 +779,119 @@ Two methods are used to indent each file in LANG-FILES,
     TAB and RET, see `t-utils--test-indent-typing'.  In tree-sitter
     modes, TAB and RET need to be handled and this verifies they are
     handled.  Error nodes are identified by using
-    ERROR-NODES-REGEXP which defaults to \"^ERROR$\".
+    ERROR-NODES-REGEXP which defaults to \"\\\\`ERROR\\\\\\='\".
+
+    The typing occurs in a temporary buffer partially named
+    \"typing__NAME.EXT\" where NAME.EXT is the basename of LANG-FILE.
+
+    The typing buffer is initialized with the string-trim'd version of
+    the non-empty lines of LANG-FILE.  If optional LINE-MANIPULATOR
+    function is specified, it is called with the typing buffer as the
+    current buffer.  LINE-MANIPULATOR should only adjust whitespace in
+    the lines.  It should not add newlines to the buffer.
+    LINE-MANIPULATOR is called from within a `save-excursion', so your
+    function doesn't need to do that.
+
+    In the typing buffer, each line is indented via
+    `indent-for-tab-command' and blank lines are inserted by calling
+    `newline'.`
+    
+Example test setup:
+
+  ./LANGUAGE-ts-mode.el
+  ./tests/test-LANUGAGE-ts-mode-indent.el
+  ./tests/test-LANUGAGE-ts-mode-indent-files/NAME1.EXT
+  ./tests/test-LANUGAGE-ts-mode-indent-files/NAME1_expected.EXT
+  ./tests/test-LANUGAGE-ts-mode-indent-files/NAME2.EXT
+  ./tests/test-LANUGAGE-ts-mode-indent-files/NAME2_expected.EXT
+
+Where ./tests/test-LANUGAGE-ts-mode-indent.el contains:
+
+  (defvar test-LANGUAGE-ts-mode-indent--file nil)
+
+  (defun test-LANGUAGE-ts-mode-indent--file (lang-file)
+    \"Test indent on LANG-FILE.\"
+    (let ((test-LANGUAGE-ts-mode-indent--file lang-file))
+      (ert-run-tests-interactively \"test-LANGUAGE-ts-mode-indent\")))
+
+  (ert-deftest test-LANGUAGE-ts-mode-indent ()
+    (let ((test-name \"test-LANGUAGE-ts-mode-indent\"))
+      (when (t-utils-is-treesit-available \\='LANGUAGE test-name)
+        (let ((lang-files (t-utils-get-files (concat test-name \"-files\") 
\"\\.EXT\\\\\\='\"
+                                          \"_expected\\.EXT\\\\\\='\" ;; skip 
our *_expected.EXT baselines
+                                          test-LANGUAGE-ts-mode-indent--file))
+              (line-manipulator nil))
+          (t-utils-test-indent test-name lang-files line-manipulator)))))
+
+To loop over all NAME*.EXT indent test files, interactively
+
+  \\[ert] RET test-LANGUAGE-ts-mode-indent RET
+
+In the *ert* buffer, you can type \"m\" at the point of the test (where
+the color marker is) to see messages that were displayed by your test.
+
+To debug a specific indent test file
+
+ M-: (test-LANGUAGE-ts-mode-indent--file \
+\"test-LANUGAGE-ts-mode-indent-files/NAME.EXT\")"
 
-See `t-utils--test-indent-type' for LINE-MANIPULATOR."
 
   (when (not error-nodes-regexp)
     (setq error-nodes-regexp (rx bos "ERROR" eos)))
 
-  (dolist (lang-file lang-files)
-    (let* ((expected-file (replace-regexp-in-string "\\.\\([^.]+\\)$" 
"_expected.\\1" lang-file))
-           (expected (when (file-exists-p expected-file)
-                       (with-temp-buffer
-                         (insert-file-contents-literally expected-file)
-                         (buffer-string))))
-           lang-file-major-mode
-           error-node)
-
-      ;; Indent lang-file
-      (with-temp-buffer
-        (let ((start-time (current-time)))
-          (t-utils--insert-file-for-test lang-file)
-          (setq error-node (treesit-search-subtree
-                            (treesit-buffer-root-node) error-nodes-regexp nil 
t))
-          (message "START: %s <indent-region> %s" test-name lang-file)
-          (setq lang-file-major-mode major-mode)
-          (indent-region (point-min) (point-max))
-          (t-utils--trim)
-          (let ((got (buffer-substring (point-min) (point-max)))
-                (got-file (concat expected-file "~")))
-            (set-buffer-modified-p nil)
-            (kill-buffer)
-            (when (not (string= got expected))
-              (let ((coding-system-for-write 'raw-text-unix))
-                (write-region got nil got-file))
-              (when (not expected)
-                (error "Baseline for %s does not exists - if %s looks good 
rename it to %s"
-                       lang-file got-file expected-file))
-              (error "Baseline for %s does not match, got: %s, expected: %s"
-                     lang-file got-file expected-file)))
-          (message "PASS: %s <indent-region> %s %s" test-name lang-file
-                   (t-utils--took start-time))))
-
-      ;; Now, simulate typing lang-file and indent it (exercise TAB and RET)
-      (when (not error-node)
-        (let ((start-time (current-time)))
+  (let ((error-msgs '()))
+    (dolist (lang-file lang-files)
+      (let* ((expected-file (replace-regexp-in-string "\\.\\([^.]+\\)\\'" 
"_expected.\\1"
+                                                      lang-file))
+             (expected (when (file-exists-p expected-file)
+                         (with-temp-buffer
+                           (insert-file-contents-literally expected-file)
+                           (buffer-string))))
+             lang-file-major-mode
+             error-node)
+
+        ;; Indent lang-file
+        (with-temp-buffer
+          (let ((start-time (current-time)))
+            (t-utils--insert-file-for-test lang-file)
+            (setq error-node (treesit-search-subtree
+                              (treesit-buffer-root-node) error-nodes-regexp 
nil t))
+
+            (message "START: %s <indent-region> %s" test-name lang-file)
+            (setq lang-file-major-mode major-mode)
+            (indent-region (point-min) (point-max))
+            (t-utils--trim)
+            (let ((got (buffer-substring (point-min) (point-max)))
+                  (got-file (concat expected-file "~")))
+              (set-buffer-modified-p nil)
+              (kill-buffer)
+
+              (let ((indent-error-msg (t-utils--baseline-check
+                                       (concat test-name " <indent-region>") 
start-time
+                                       lang-file got got-file expected 
expected-file)))
+                (when indent-error-msg
+                  (push indent-error-msg error-msgs))))))
+
+        ;; Now, simulate typing lang-file and indent it (exercise TAB and RET)
+        (when (not error-node)
           (message "START: %s <indent-via-typing> %s" test-name lang-file)
-          (t-utils--test-indent-typing lang-file lang-file-major-mode
-                                       expected expected-file
-                                       line-manipulator)
-          (message "PASS: %s <indent-via-typing> %s %s" test-name lang-file
-                   (t-utils--took start-time)))))))
+          (let ((start-time (current-time))
+                (typing-error-msg (t-utils--test-indent-typing lang-file 
lang-file-major-mode
+                                                               expected 
expected-file
+                                                               
line-manipulator)))
+            (message "%s: %s <indent-via-typing> %s %s" test-name lang-file
+                     (if typing-error-msg "FAIL" "PASS")
+                     (t-utils--took start-time))
+            (when typing-error-msg
+              (push typing-error-msg error-msgs))))
+        ))
+    ;; Validate t-utils-test-indent result
+    (setq error-msgs (reverse error-msgs))
+    (should (equal error-msgs '()))))
 
 (defun t-utils--check-parse (lang-file error-nodes-regexp syntax-checker-fun 
check-valid-parse)
   "Return (parse-error . invalid-successful-parse) pair of strings.
+This looks for ERROR-NODES-REGEXP in the tree-sitter parse tree.
 See `t-utils-sweep-test-indent' for a description of
 LANG-FILE ERROR-NODES-REGEXP SYNTAX-CHECKER-FUN CHECK-VALID-PARSE."
 
@@ -947,49 +1128,52 @@ to NAME_expected.txt.
 To add a test for TEST-NAME.el which call this function, in the
 corresponding TEST-NAME-files/ directory, create
 TEST-NAME-files/NAME.EXT, then run the test.  Follow the messages to
-accept the generated baseline after validating it."
+accept the generated baseline after validating it.
 
-  (dolist (lang-file lang-files)
-    (with-temp-buffer
+TODO should example test setup, see t-utils-test-font-lock."
 
-      (let ((start-time (current-time)))
-        (message "START: %s %s" test-name lang-file)
+  (let ((error-msgs '()))
+    (dolist (lang-file lang-files)
+      (with-temp-buffer
 
-        (t-utils--insert-file-for-test lang-file)
+        (let ((start-time (current-time)))
+          (message "START: %s %s" test-name lang-file)
 
-        (let* ((got "")
-               (expected-file (replace-regexp-in-string "\\.[^.]+$" 
"_expected.txt" lang-file))
-               (got-file (concat expected-file "~"))
-               (expected (when (file-exists-p expected-file)
-                           (with-temp-buffer
-                             (insert-file-contents-literally expected-file)
-                             (buffer-string)))))
-          (forward-line) ;; skip the mode line specification
-          (while (not (eobp))
-            (when (looking-at "^")
-              (setq got (concat got (format "Line:%d: %s\n"
-                                            (line-number-at-pos)
-                                            (buffer-substring-no-properties 
(point)
-                                                                            
(line-end-position))))))
-
-            (let ((char (buffer-substring-no-properties (point) (1+ (point)))))
-              (when (string= char "\n")
-                (setq char "\\n"))
-              (setq got (concat got (format "  %2s: %S\n" char (syntax-ppss 
(point))))))
-
-            (forward-char))
+          (t-utils--insert-file-for-test lang-file)
 
-          (kill-buffer)
-          (when (not (string= got expected))
-            (let ((coding-system-for-write 'raw-text-unix))
-              (write-region got nil got-file))
-            (when (not expected)
-              (error "Baseline for %s does not exists.  \
-See %s and if it looks good rename it to %s"
-                     lang-file got-file expected-file))
-            (error "Baseline for %s does not match, got: %s, expected: %s"
-                   lang-file got-file expected-file)))
-        (message "PASS: %s %s %s" test-name lang-file (t-utils--took 
start-time))))))
+          (let* ((got "")
+                 (expected-file (replace-regexp-in-string "\\.[^.]+\\'" 
"_expected.txt" lang-file))
+                 (got-file (concat expected-file "~"))
+                 (expected (when (file-exists-p expected-file)
+                             (with-temp-buffer
+                               (insert-file-contents-literally expected-file)
+                               (buffer-string)))))
+            (forward-line) ;; skip the mode line specification
+            (while (not (eobp))
+              (when (looking-at "^")
+                (setq got (concat got (format
+                                       "Line:%d: %s\n"
+                                       (line-number-at-pos)
+                                       (buffer-substring-no-properties (point)
+                                                                       
(line-end-position))))))
+
+              (let ((char (buffer-substring-no-properties (point) (1+ 
(point)))))
+                (when (string= char "\n")
+                  (setq char "\\n"))
+                (setq got (concat got (format "  %2s: %S\n" char (syntax-ppss 
(point))))))
+
+              (forward-char))
+
+            (kill-buffer)
+
+            (let ((error-msg (t-utils--baseline-check
+                              test-name start-time
+                              lang-file got got-file expected expected-file)))
+              (when error-msg
+                (push error-msg error-msgs)))))))
+    ;; Validate t-utils-test-syntax-table result
+    (setq error-msgs (reverse error-msgs))
+    (should (equal error-msgs '()))))
 
 (defun t-utils-test-treesit-defun-name (test-name lang-files)
   "Test `treesit-defun-name-function' setup.
@@ -1005,49 +1189,53 @@ to NAME_expected.txt.
 To add a test for TEST-NAME.el which call this function, in the
 corresponding TEST-NAME-files/ directory, create
 TEST-NAME-files/NAME.EXT, then run the test.  Follow the messages to
-accept the generated baseline after validating it."
+accept the generated baseline after validating it.
 
-  (dolist (lang-file lang-files)
-    (with-temp-buffer
+TODO should example test setup, see t-utils-test-font-lock."
 
-      (let ((start-time (current-time)))
-        (message "START: %s %s" test-name lang-file)
+  (let ((error-msgs '()))
+    (dolist (lang-file lang-files)
+      (with-temp-buffer
 
-        (t-utils--insert-file-for-test lang-file)
+        (let ((start-time (current-time)))
+          (message "START: %s %s" test-name lang-file)
 
-        (let* ((root (treesit-buffer-root-node))
-               (expected-file (replace-regexp-in-string "\\.[^.]+$" 
"_expected.txt" lang-file))
-               (expected (when (file-exists-p expected-file)
-                           (with-temp-buffer
-                             (insert-file-contents-literally expected-file)
-                             (buffer-string))))
-               (got "")
-               (got-file (concat expected-file "~")))
+          (t-utils--insert-file-for-test lang-file)
 
-          (treesit-search-subtree
-           root
-           (lambda (node)
-             (let ((defun-name (funcall treesit-defun-name-function node))
-                   (node-type (replace-regexp-in-string "\n" "\\n" 
(treesit-node-type node)))
-                   (node-start (treesit-node-start node))
-                   (node-end (treesit-node-end node)))
-               (setq got (concat
-                          got
-                          (format "Node %25s at %4d to %4d: defun-name = %s\n"
-                                  node-type node-start node-end (if defun-name 
defun-name "nil")))))
-             nil))
+          (let* ((root (treesit-buffer-root-node))
+                 (expected-file (replace-regexp-in-string "\\.[^.]+\\'" 
"_expected.txt" lang-file))
+                 (expected (when (file-exists-p expected-file)
+                             (with-temp-buffer
+                               (insert-file-contents-literally expected-file)
+                               (buffer-string))))
+                 (got "")
+                 (got-file (concat expected-file "~")))
 
-          (kill-buffer)
-          (when (not (string= got expected))
-            (let ((coding-system-for-write 'raw-text-unix))
-              (write-region got nil got-file))
-            (when (not expected)
-              (error "Baseline for %s does not exists.  \
-See %s and if it looks good rename it to %s"
-                     lang-file got-file expected-file))
-            (error "Baseline for %s does not match, got: %s, expected: %s"
-                   lang-file got-file expected-file)))
-        (message "PASS: %s %s %s" test-name lang-file (t-utils--took 
start-time))))))
+            (treesit-search-subtree
+             root
+             (lambda (node)
+               (let ((defun-name (funcall treesit-defun-name-function node))
+                     (node-type (replace-regexp-in-string "\n" "\\n" 
(treesit-node-type node)))
+                     (node-start (treesit-node-start node))
+                     (node-end (treesit-node-end node)))
+                 (setq got (concat
+                            got
+                            (format "Node %25s at %4d to %4d: defun-name = 
%s\n"
+                                    node-type node-start node-end
+                                    (if defun-name defun-name "nil")))))
+               nil))
+
+            (kill-buffer)
+
+            (let ((error-msg (t-utils--baseline-check
+                              test-name start-time
+                              lang-file got got-file expected expected-file)))
+              (when error-msg
+                (push error-msg error-msgs)))))))
+
+    ;; Validate t-utils-test-treesit-defun-name result
+    (setq error-msgs (reverse error-msgs))
+    (should (equal error-msgs '()))))
 
 (defun t-utils-test-imenu (test-name lang-files)
   "Test imenu support.
@@ -1062,39 +1250,40 @@ to NAME_expected.txt.
 To add a test for TEST-NAME.el which call this function, in the
 corresponding TEST-NAME-files/ directory, create
 TEST-NAME-files/NAME.EXT, then run the test.  Follow the messages to
-accept the generated baseline after validating it."
+accept the generated baseline after validating it.
 
-  (dolist (lang-file lang-files)
-    (with-temp-buffer
+TODO should example test setup, see t-utils-test-font-lock."
 
-      (let ((start-time (current-time)))
-        (message "START: %s %s" test-name lang-file)
+  (let ((error-msgs '()))
+    (dolist (lang-file lang-files)
+      (with-temp-buffer
 
-        (t-utils--insert-file-for-test lang-file)
+        (let ((start-time (current-time)))
+          (message "START: %s %s" test-name lang-file)
 
-        (let* ((index (funcall imenu-create-index-function))
-               (expected-file (replace-regexp-in-string "\\.[^.]+$" 
"_expected.txt" lang-file))
-               (expected (when (file-exists-p expected-file)
-                           (with-temp-buffer
-                             (insert-file-contents-literally expected-file)
-                             (buffer-string))))
-               (got (concat (string-join
-                             (mapcar (lambda (el) (substring-no-properties 
(car el))) index)
-                             "\n")
-                            "\n"))
-               (got-file (concat expected-file "~")))
+          (t-utils--insert-file-for-test lang-file)
 
-          (kill-buffer)
-          (when (not (string= got expected))
-            (let ((coding-system-for-write 'raw-text-unix))
-              (write-region got nil got-file))
-            (when (not expected)
-              (error "Baseline for %s does not exists.  \
-See %s and if it looks good rename it to %s"
-                     lang-file got-file expected-file))
-            (error "Baseline for %s does not match, got: %s, expected: %s"
-                   lang-file got-file expected-file)))
-        (message "PASS: %s %s %s" test-name lang-file (t-utils--took 
start-time))))))
+          (let* ((index (funcall imenu-create-index-function))
+                 (expected-file (replace-regexp-in-string "\\.[^.]+\\'" 
"_expected.txt" lang-file))
+                 (expected (when (file-exists-p expected-file)
+                             (with-temp-buffer
+                               (insert-file-contents-literally expected-file)
+                               (buffer-string))))
+                 (got (concat (string-join
+                               (mapcar (lambda (el) (substring-no-properties 
(car el))) index)
+                               "\n")
+                              "\n"))
+                 (got-file (concat expected-file "~")))
+
+            (kill-buffer)
+            (let ((error-msg (t-utils--baseline-check
+                              test-name start-time
+                              lang-file got got-file expected expected-file)))
+              (when error-msg
+                (push error-msg error-msgs)))))))
+    ;; Validate t-utils-test-imenu result
+    (setq error-msgs (reverse error-msgs))
+    (should (equal error-msgs '()))))
 
 (defun t-utils-test-outline-search-function (test-name lang-files)
   "Test setup for `outline-minor-mode'.
@@ -1109,48 +1298,51 @@ to NAME_expected.txt.
 To add a test for TEST-NAME.el which call this function, in the
 corresponding TEST-NAME-files/ directory, create
 TEST-NAME-files/NAME.EXT, then run the test.  Follow the messages to
-accept the generated baseline after validating it."
+accept the generated baseline after validating it.
 
-  (dolist (lang-file lang-files)
-    (with-temp-buffer
+TODO should example test setup, see t-utils-test-font-lock."
 
-      (let ((start-time (current-time))
-            (lang-file-base (file-name-nondirectory lang-file)))
-        (message "START: %s %s" test-name lang-file)
+  (let ((error-msgs '()))
+    (dolist (lang-file lang-files)
+      (with-temp-buffer
 
-        (t-utils--insert-file-for-test lang-file)
+        (let ((start-time (current-time))
+              (lang-file-base (file-name-nondirectory lang-file)))
 
-        (let* ((expected-file (replace-regexp-in-string "\\.[^.]+$" 
"_expected.txt" lang-file))
-               (expected (when (file-exists-p expected-file)
-                           (with-temp-buffer
-                             (insert-file-contents-literally expected-file)
-                             (buffer-string))))
-               (got "Section heading lines\n\n")
-               (got-file (concat expected-file "~")))
+          (message "START: %s %s" test-name lang-file)
 
-          (while (not (eobp))
-            (let ((next-heading (funcall outline-search-function)))
-              (if next-heading
-                  (let ((heading-info (format "%s:%d: %s\n"
-                                              lang-file-base
-                                              (line-number-at-pos)
-                                              (buffer-substring-no-properties
-                                               (line-beginning-position) 
(line-end-position)))))
-                    (setq got (concat got heading-info))
-                    (forward-line))
-                (goto-char (point-max)))))
+          (t-utils--insert-file-for-test lang-file)
+
+          (let* ((expected-file (replace-regexp-in-string "\\.[^.]+\\'" 
"_expected.txt" lang-file))
+                 (expected (when (file-exists-p expected-file)
+                             (with-temp-buffer
+                               (insert-file-contents-literally expected-file)
+                               (buffer-string))))
+                 (got "Section heading lines\n\n")
+                 (got-file (concat expected-file "~")))
+
+            (while (not (eobp))
+              (let ((next-heading (funcall outline-search-function)))
+                (if next-heading
+                    (let ((heading-info (format "%s:%d: %s\n"
+                                                lang-file-base
+                                                (line-number-at-pos)
+                                                (buffer-substring-no-properties
+                                                 (line-beginning-position) 
(line-end-position)))))
+                      (setq got (concat got heading-info))
+                      (forward-line))
+                  (goto-char (point-max)))))
+
+            (kill-buffer)
+            (let ((error-msg (t-utils--baseline-check
+                              test-name start-time
+                              lang-file got got-file expected expected-file)))
+              (when error-msg
+                (push error-msg error-msgs)))))))
+    ;; Validate t-utils-test-outline-search-function result
+    (setq error-msgs (reverse error-msgs))
+    (should (equal error-msgs '()))))
 
-          (kill-buffer)
-          (when (not (string= got expected))
-            (let ((coding-system-for-write 'raw-text-unix))
-              (write-region got nil got-file))
-            (when (not expected)
-              (error "Baseline for %s does not exists.  \
-See %s and if it looks good rename it to %s"
-                     lang-file got-file expected-file))
-            (error "Baseline for %s does not match, got: %s, expected: %s"
-                   lang-file got-file expected-file)))
-        (message "PASS: %s %s %s" test-name lang-file (t-utils--took 
start-time))))))
 
 (provide 't-utils)
 ;;; t-utils.el ends here
diff --git a/tests/test-matlab-ts-mode-comments.el 
b/tests/test-matlab-ts-mode-comments.el
index 00864a2dd1..706edf7f5d 100644
--- a/tests/test-matlab-ts-mode-comments.el
+++ b/tests/test-matlab-ts-mode-comments.el
@@ -30,13 +30,21 @@
 (require 't-utils)
 (require 'matlab-ts-mode)
 
-(cl-defun test-matlab-ts-mode-comments (&optional m-file)
-  "Test defun movement using ./test-matlab-ts-mode-comments-files/NAME.m.
+(defvar test-matlab-ts-mode-comments--file nil)
+
+(defun test-matlab-ts-mode-comments--file (m-file)
+  "Test an individual M-FILE.
+This is provided for debugging.
+  M-: (test-matlab-ts-mode-comments--file 
\"test-matlab-ts-mode-comments-files/M-FILE\")"
+  (let ((test-matlab-ts-mode-comments--file m-file))
+    (ert-run-tests-interactively "test-matlab-ts-mode-comments")))
+
+(ert-deftest test-matlab-ts-mode-comments ()
+  "Test comments using ./test-matlab-ts-mode-comments-files/NAME.m.
 Using ./test-matlab-ts-mode-comments-files/NAME.m, compare comment
-keybindings against
-./test-matlab-ts-mode-comments-files/NAME_expected.org.  If M-FILE is
-not provided, loop comparing all
-./test-matlab-ts-mode-comments-files/NAME.m files.
+key bindings against
+./test-matlab-ts-mode-comments-files/NAME_expected.org.  This loops
+on all ./test-matlab-ts-mode-comments-files/NAME.m files.
 
 To add a test, create
   ./test-matlab-ts-mode-comments-files/NAME.m
@@ -46,13 +54,10 @@ after validating it, rename it to
   ./test-matlab-ts-mode-comments-files/NAME_expected.org"
 
   (let ((test-name "test-matlab-ts-mode-comments"))
-
-    (when (not (t-utils-is-treesit-available 'matlab test-name))
-      (cl-return-from test-matlab-ts-mode-comments))
-
-    (let ((m-files (t-utils-get-files (concat test-name "-files") "\\.m$" nil 
m-file)))
-      (t-utils-test-xr test-name m-files)))
-    "success")
+    (when (t-utils-is-treesit-available 'matlab test-name)
+      (let ((m-files (t-utils-get-files (concat test-name "-files") "\\.m\\'" 
nil
+                                        test-matlab-ts-mode-comments--file)))
+        (t-utils-test-xr test-name m-files)))))
 
 (provide 'test-matlab-ts-mode-comments)
 ;;; test-matlab-ts-mode-comments.el ends here
diff --git a/tests/test-matlab-ts-mode-electric-pair.el 
b/tests/test-matlab-ts-mode-electric-pair.el
index 90024e08c1..697fb08069 100644
--- a/tests/test-matlab-ts-mode-electric-pair.el
+++ b/tests/test-matlab-ts-mode-electric-pair.el
@@ -30,13 +30,21 @@
 (require 't-utils)
 (require 'matlab-ts-mode)
 
-(cl-defun test-matlab-ts-mode-electric-pair (&optional m-file)
-  "Test defun movement using ./test-matlab-ts-mode-electric-pair-files/NAME.m.
-Using ./test-matlab-ts-mode-electric-pair-files/NAME.m, compare defun
-movement against
-./test-matlab-ts-mode-electric-pair-files/NAME_expected.org.  If M-FILE is
-not provided, loop comparing all
-./test-matlab-ts-mode-electric-pair-files/NAME.m files.
+(defvar test-matlab-ts-mode-electric-pair--file nil)
+
+(defun test-matlab-ts-mode-electric-pair--file (m-file)
+  "Test an individual M-FILE.
+This is provided for debugging.
+  M-: (test-matlab-ts-mode-electric-pair--file 
\"test-matlab-ts-mode-electric-pair-files/M-FILE\")"
+  (let ((test-matlab-ts-mode-electric-pair--file m-file))
+    (ert-run-tests-interactively "test-matlab-ts-mode-electric-pair")))
+
+(ert-deftest test-matlab-ts-mode-electric-pair ()
+  "Test electric pair using ./test-matlab-ts-mode-electric-pair-files/NAME.m.
+Using ./test-matlab-ts-mode-electric-pair-files/NAME.m, run
+`matlab-ts-mode--electric-pair-inhibit-predicate' compare result against
+./test-matlab-ts-mode-electric-pair-files/NAME_expected.org.  This loops
+on all ./test-matlab-ts-mode-comments-files/NAME.m files.
 
 To add a test, create
   ./test-matlab-ts-mode-electric-pair-files/NAME.m
@@ -46,13 +54,10 @@ after validating it, rename it to
   ./test-matlab-ts-mode-electric-pair-files/NAME_expected.org"
 
   (let ((test-name "test-matlab-ts-mode-electric-pair"))
-
-    (when (not (t-utils-is-treesit-available 'matlab test-name))
-      (cl-return-from test-matlab-ts-mode-electric-pair))
-
-    (let ((m-files (t-utils-get-files (concat test-name "-files") "\\.m$" nil 
m-file)))
-      (t-utils-test-xr test-name m-files)))
-    "success")
+    (when (t-utils-is-treesit-available 'matlab test-name)
+      (let ((m-files (t-utils-get-files (concat test-name "-files") "\\.m\\'" 
nil
+                                        
test-matlab-ts-mode-electric-pair--file)))
+        (t-utils-test-xr test-name m-files)))))
 
 (provide 'test-matlab-ts-mode-electric-pair)
 ;;; test-matlab-ts-mode-electric-pair.el ends here
diff --git a/tests/test-matlab-ts-mode-fill-paragraph.el 
b/tests/test-matlab-ts-mode-fill-paragraph.el
index f6490de6b5..3f2e59b0bd 100644
--- a/tests/test-matlab-ts-mode-fill-paragraph.el
+++ b/tests/test-matlab-ts-mode-fill-paragraph.el
@@ -30,13 +30,22 @@
 (require 't-utils)
 (require 'matlab-ts-mode)
 
-(cl-defun test-matlab-ts-mode-fill-paragraph (&optional m-file)
-  "Test defun movement using ./test-matlab-ts-mode-fill-paragraph-files/NAME.m.
-Using ./test-matlab-ts-mode-fill-paragraph-files/NAME.m, compare comment
-keybindings against
-./test-matlab-ts-mode-fill-paragraph-files/NAME_expected.org.  If M-FILE is
-not provided, loop comparing all
-./test-matlab-ts-mode-fill-paragraph-files/NAME.m files.
+(defvar test-matlab-ts-mode-fill-paragraph--file nil)
+
+(defun test-matlab-ts-mode-fill-paragraph--file (m-file)
+  "Test an individual M-FILE.
+This is provided for debugging.
+  M-: (test-matlab-ts-mode-fill-paragraph--file
+       \"test-matlab-ts-mode-fill-paragraph-files/M-FILE\")"
+  (let ((test-matlab-ts-mode-fill-paragraph--file m-file))
+    (ert-run-tests-interactively "test-matlab-ts-mode-fill-paragraph")))
+
+(ert-deftest test-matlab-ts-mode-fill-paragraph ()
+  "Test fill paragraph using ./test-matlab-ts-mode-fill-paragraph-files/NAME.m.
+Using ./test-matlab-ts-mode-fill-paragraph-files/NAME.m, run
+`fill-paragraph' and compare result against
+./test-matlab-ts-mode-fill-paragraph-files/NAME_expected.org.  This loops
+on all ./test-matlab-ts-mode-comments-files/NAME.m files.
 
 To add a test, create
   ./test-matlab-ts-mode-fill-paragraph-files/NAME.m
@@ -50,9 +59,9 @@ after validating it, rename it to
     (when (not (t-utils-is-treesit-available 'matlab test-name))
       (cl-return-from test-matlab-ts-mode-fill-paragraph))
 
-    (let ((m-files (t-utils-get-files (concat test-name "-files") "\\.m$" nil 
m-file)))
-      (t-utils-test-xr test-name m-files)))
-    "success")
+    (let ((m-files (t-utils-get-files (concat test-name "-files") "\\.m\\'" nil
+                                      
test-matlab-ts-mode-fill-paragraph--file)))
+      (t-utils-test-xr test-name m-files))))
 
 (provide 'test-matlab-ts-mode-fill-paragraph)
 ;;; test-matlab-ts-mode-fill-paragraph.el ends here
diff --git a/tests/test-matlab-ts-mode-font-lock.el 
b/tests/test-matlab-ts-mode-font-lock.el
index 5514a24e89..c788fe943d 100644
--- a/tests/test-matlab-ts-mode-font-lock.el
+++ b/tests/test-matlab-ts-mode-font-lock.el
@@ -28,58 +28,64 @@
 (require 't-utils)
 (require 'matlab-ts-mode)
 
-(cl-defun test-matlab-ts-mode-font-lock (&optional m-file)
+(defvar test-matlab-ts-mode-font-lock--file nil)
+
+(defun test-matlab-ts-mode-font-lock--file (m-file)
+  "Test an individual M-FILE.
+This is provided for debugging.
+  M-: (test-matlab-ts-mode-font-lock--file 
\"test-matlab-ts-mode-font-lock-files/M-FILE\")"
+  (let ((test-matlab-ts-mode-font-lock--file m-file))
+    (ert-run-tests-interactively "test-matlab-ts-mode-font-lock")))
+
+(ert-deftest test-matlab-ts-mode-font-lock ()
   "Test font-lock using ./test-matlab-ts-mode-font-lock-files/NAME.m.
-Compare ./test-matlab-ts-mode-font-lock-files/NAME.m against
+Compare font of ./test-matlab-ts-mode-font-lock-files/NAME.m against
 ./test-matlab-ts-mode-font-lock-files/NAME_expected.txt, where
 NAME_expected.txt is of same length as NAME.m where each source
 character in NAME.m is replaced with a character code representing the
 font-lock face used for said source character.  The mapping is defined
-by the code-to-face alist setup by this function.  If M-FILE is not
-provided, loop comparing all
-./test-matlab-ts-mode-font-lock-files/NAME.m files.
+by the code-to-face alist setup by this function.  This loops
+on all ./test-matlab-ts-mode-font-lock-files/NAME.m files.
 
-To add a test, create
+To add a test, createp
   ./test-matlab-ts-mode-font-lock-files/NAME.m
 and run this function.  The baseline is saved for you as
-  ./test-matlab-ts-mode-font-lock-files/NAME_expected.m~
+  ./test-matlab-ts-mode-font-lock-files/NAME_expected.txt~
 after validating it, rename it to
-  ./test-matlab-ts-mode-font-lock-files/NAME_expected.m"
-
-  (let ((test-name "test-matlab-ts-mode-font-lock")
-        (matlab-ts-mode-font-lock-level 4))
-    (when (not (t-utils-is-treesit-available 'matlab test-name))
-      (cl-return-from test-matlab-ts-mode-font-lock))
+  ./test-matlab-ts-mode-font-lock-files/NAME_expected.txt"
 
-    (let* ((m-files (t-utils-get-files (concat test-name "-files") "\\.m$" nil 
m-file))
-           (code-to-face '(
-                           ("!" . matlab-ts-mode-system-command-face)
-                           ("a" . matlab-ts-mode-command-arg-face)
-                           ("b" . font-lock-bracket-face)
-                           ("B" . font-lock-builtin-face)
-                           ("c" . font-lock-comment-face)
-                           ("C" . font-lock-comment-delimiter-face)
-                           ("d" . default)
-                           ("D" . font-lock-delimiter-face)
-                           ("E" . font-lock-escape-face)
-                           ("f" . font-lock-function-name-face)
-                           ("F" . font-lock-function-call-face)
-                           ("h" . font-lock-doc-face) ;; function doc help 
comment
-                           ("H" . matlab-ts-mode-comment-heading-face)
-                           ("k" . font-lock-keyword-face)
-                           ("M" . matlab-ts-mode-comment-to-do-marker-face)
-                           ("n" . matlab-ts-mode-number-face)
-                           ("s" . font-lock-string-face)
-                           ("S" . matlab-ts-mode-string-delimiter-face)
-                           ("o" . matlab-ts-mode-operator-face)
-                           ("p" . matlab-ts-mode-pragma-face)
-                           ("P" . matlab-ts-mode-property-face)
-                           ("t" . font-lock-type-face)
-                           ("v" . font-lock-variable-name-face)
-                           ("w" . font-lock-warning-face)
-                           )))
-      (t-utils-test-font-lock test-name m-files code-to-face))
-    "success"))
+  (let ((test-name "test-matlab-ts-mode-font-lock"))
+    (when (t-utils-is-treesit-available 'matlab test-name)
+      (let* ((matlab-ts-mode-font-lock-level 4)
+             (m-files (t-utils-get-files (concat test-name "-files") "\\.m\\'" 
nil
+                                         test-matlab-ts-mode-font-lock--file))
+             (code-to-face '(
+                             ("!" . matlab-ts-mode-system-command-face)
+                             ("a" . matlab-ts-mode-command-arg-face)
+                             ("b" . font-lock-bracket-face)
+                             ("B" . font-lock-builtin-face)
+                             ("c" . font-lock-comment-face)
+                             ("C" . font-lock-comment-delimiter-face)
+                             ("d" . default)
+                             ("D" . font-lock-delimiter-face)
+                             ("E" . font-lock-escape-face)
+                             ("f" . font-lock-function-name-face)
+                             ("F" . font-lock-function-call-face)
+                             ("h" . font-lock-doc-face) ;; function doc help 
comment
+                             ("H" . matlab-ts-mode-comment-heading-face)
+                             ("k" . font-lock-keyword-face)
+                             ("M" . matlab-ts-mode-comment-to-do-marker-face)
+                             ("n" . matlab-ts-mode-number-face)
+                             ("s" . font-lock-string-face)
+                             ("S" . matlab-ts-mode-string-delimiter-face)
+                             ("o" . matlab-ts-mode-operator-face)
+                             ("p" . matlab-ts-mode-pragma-face)
+                             ("P" . matlab-ts-mode-property-face)
+                             ("t" . font-lock-type-face)
+                             ("v" . font-lock-variable-name-face)
+                             ("w" . font-lock-warning-face)
+                             )))
+        (t-utils-test-font-lock test-name m-files code-to-face)))))
 
 (provide 'test-matlab-ts-mode-font-lock)
 ;;; test-matlab-ts-mode-font-lock.el ends here
diff --git a/tests/test-matlab-ts-mode-imenu.el 
b/tests/test-matlab-ts-mode-imenu.el
index 3066cceaa5..b5919a845b 100644
--- a/tests/test-matlab-ts-mode-imenu.el
+++ b/tests/test-matlab-ts-mode-imenu.el
@@ -30,12 +30,20 @@
 (require 't-utils)
 (require 'matlab-ts-mode)
 
-(cl-defun test-matlab-ts-mode-imenu (&optional m-file)
-  "Test defun movement using ./test-matlab-ts-mode-imenu-files/NAME.m.
+(defvar test-matlab-ts-mode-imenu--file nil)
+
+(defun test-matlab-ts-mode-imenu--file (m-file)
+  "Test an individual M-FILE.
+This is provided for debugging.
+  M-: (test-matlab-ts-mode-imenu--file 
\"test-matlab-ts-mode-imenu-files/M-FILE\")"
+  (let ((test-matlab-ts-mode-imenu--file m-file))
+    (ert-run-tests-interactively "test-matlab-ts-mode-imenu")))
+
+(ert-deftest test-matlab-ts-mode-imenu ()
+  "Test imenu using ./test-matlab-ts-mode-imenu-files/NAME.m.
 Using ./test-matlab-ts-mode-imenu-files/NAME.m, compare imenu results
-against ./test-matlab-ts-mode-imenu-files/NAME_expected.txt.  If M-FILE
-is not provided, loop comparing all
-./test-matlab-ts-mode-imenu-files/NAME.m files.
+against ./test-matlab-ts-mode-imenu-files/NAME_expected.txt.  This loops
+on all ./test-matlab-ts-mode-imenu-files/NAME.m files.
 
 To add a test, create
   ./test-matlab-ts-mode-imenu-files/NAME.m
@@ -45,13 +53,10 @@ after validating it, rename it to
   ./test-matlab-ts-mode-imenu-files/NAME_expected.txt"
 
   (let ((test-name "test-matlab-ts-mode-imenu"))
-
-    (when (not (t-utils-is-treesit-available 'matlab test-name))
-      (cl-return-from test-matlab-ts-mode-imenu))
-
-    (let ((m-files (t-utils-get-files (concat test-name "-files") "\\.m$" nil 
m-file)))
-      (t-utils-test-imenu test-name m-files)))
-    "success")
+    (when (t-utils-is-treesit-available 'matlab test-name)
+      (let ((m-files (t-utils-get-files (concat test-name "-files") "\\.m\\'" 
nil
+                                        test-matlab-ts-mode-imenu--file)))
+        (t-utils-test-imenu test-name m-files)))))
 
 (provide 'test-matlab-ts-mode-imenu)
 ;;; test-matlab-ts-mode-imenu.el ends here
diff --git a/tests/test-matlab-ts-mode-indent.el 
b/tests/test-matlab-ts-mode-indent.el
index a6acaf0848..9861acb9a8 100644
--- a/tests/test-matlab-ts-mode-indent.el
+++ b/tests/test-matlab-ts-mode-indent.el
@@ -30,12 +30,21 @@
 (require 't-utils)
 (require 'matlab-ts-mode)
 
-(cl-defun test-matlab-ts-mode-indent (&optional m-file)
+(defvar test-matlab-ts-mode-indent--file nil)
+
+(defun test-matlab-ts-mode-indent--file (m-file)
+  "Test an individual M-FILE.
+This is provided for debugging.
+  M-: (test-matlab-ts-mode-indent--file 
\"test-matlab-ts-mode-indent-files/M-FILE\")"
+  (let ((test-matlab-ts-mode-indent--file m-file))
+    (ert-run-tests-interactively "test-matlab-ts-mode-indent")))
+
+(ert-deftest test-matlab-ts-mode-indent ()
   "Test indent using ./test-matlab-ts-mode-indent-files/NAME.m.
 Compare indent of ./test-matlab-ts-mode-indent-files/NAME.m against
 ./test-matlab-ts-mode-indent-files/NAME_expected.m.  Indent is done two
-ways as described in `t-utils-test-indent'.  If M-FILE is not provided,
-loop comparing all ./test-matlab-ts-mode-indent-files/NAME.m files.
+ways as described in `t-utils-test-indent'.  This loops
+on all ./test-matlab-ts-mode-indent-files/NAME.m files.
 
 To add a test, create
   ./test-matlab-ts-mode-indent-files/NAME.m
@@ -44,28 +53,23 @@ and run this function.  The baseline is saved for you as
 after validating it, rename it to
   ./test-matlab-ts-mode-indent-files/NAME_expected.m"
 
-  (let ((test-name "test-matlab-ts-mode-indent")
-        (matlab-ts-mode--indent-assert t))
-
-    (when (not (t-utils-is-treesit-available 'matlab test-name))
-      (cl-return-from test-matlab-ts-mode-indent))
-
-    (let ((m-files (t-utils-get-files (concat test-name "-files") "\\.m$"
-                                      "_expected\\.m$" ;; skip our 
*_expected.m baselines
-                                      m-file))
-          (line-manipulator (lambda ()
-                              ;; Workaround
-                              ;; 
https://github.com/acristoffers/tree-sitter-matlab/issues/32
-                              (goto-char (point-min))
-                              (while (not (eobp))
-                                (let* ((node   (treesit-node-at (point)))
-                                       (parent (and node (treesit-node-parent 
node))))
-                                  (when (string= (treesit-node-type parent) 
"ERROR")
-                                    (insert " ")))
-                                (forward-line)))))
+  (let ((test-name "test-matlab-ts-mode-indent"))
+    (when (t-utils-is-treesit-available 'matlab test-name)
+      (let ((m-files (t-utils-get-files (concat test-name "-files") "\\.m\\'"
+                                        "_expected\\.m\\'" ;; skip our 
*_expected.m baselines
+                                        test-matlab-ts-mode-indent--file))
+            (line-manipulator (lambda ()
+                                ;; Workaround
+                                ;; 
https://github.com/acristoffers/tree-sitter-matlab/issues/32
+                                (goto-char (point-min))
+                                (while (not (eobp))
+                                  (let* ((node   (treesit-node-at (point)))
+                                         (parent (and node 
(treesit-node-parent node))))
+                                    (when (string= (treesit-node-type parent) 
"ERROR")
+                                      (insert " ")))
+                                  (forward-line)))))
 
-      (t-utils-test-indent test-name m-files line-manipulator)))
-    "success")
+        (t-utils-test-indent test-name m-files line-manipulator)))))
 
 (provide 'test-matlab-ts-mode-indent)
 ;;; test-matlab-ts-mode-indent.el ends here
diff --git a/tests/test-matlab-ts-mode-on-save-fixes.el 
b/tests/test-matlab-ts-mode-on-save-fixes.el
index 8bf5145874..7ed2642e24 100644
--- a/tests/test-matlab-ts-mode-on-save-fixes.el
+++ b/tests/test-matlab-ts-mode-on-save-fixes.el
@@ -30,13 +30,22 @@
 (require 't-utils)
 (require 'matlab-ts-mode)
 
-(cl-defun test-matlab-ts-mode-on-save-fixes (&optional m-file)
-  "Test defun movement using ./test-matlab-ts-mode-on-save-fixes-files/NAME.m.
-Using ./test-matlab-ts-mode-on-save-fixes-files/NAME.m, compare defun
-movement against
-./test-matlab-ts-mode-on-save-fixes-files/NAME_expected.org.  If M-FILE is
-not provided, loop comparing all
-./test-matlab-ts-mode-on-save-fixes-files/NAME.m files.
+(defvar test-matlab-ts-mode-on-save-fixes--file nil)
+
+(defun test-matlab-ts-mode-on-save-fixes--file (m-file)
+  "Test an individual M-FILE.
+This is provided for debugging.
+  M-: (test-matlab-ts-mode-on-save-fixes--file 
\"test-matlab-ts-mode-on-save-fixes-files/M-FILE\")"
+  (let ((test-matlab-ts-mode-on-save-fixes--file m-file))
+    (ert-run-tests-interactively "test-matlab-ts-mode-on-save-fixes")))
+
+(ert-deftest test-matlab-ts-mode-on-save-fixes ()
+  "Test fix of fcn name using ./test-matlab-ts-mode-on-save-fixes-files/NAME.m.
+Using ./test-matlab-ts-mode-on-save-fixes-files/NAME.m, set the
+buffer name to \"tmp__NAME.m\" and validate
+`matlab-ts-mode-on-save-fix-name' returns expected result found in
+./test-matlab-ts-mode-on-save-fixes-files/NAME_expected.org.  This loops
+on all ./test-matlab-ts-mode-on-save-fixes-files/NAME.m files.
 
 To add a test, create
   ./test-matlab-ts-mode-on-save-fixes-files/NAME.m
@@ -46,13 +55,10 @@ after validating it, rename it to
   ./test-matlab-ts-mode-on-save-fixes-files/NAME_expected.org"
 
   (let ((test-name "test-matlab-ts-mode-on-save-fixes"))
-
-    (when (not (t-utils-is-treesit-available 'matlab test-name))
-      (cl-return-from test-matlab-ts-mode-on-save-fixes))
-
-    (let ((m-files (t-utils-get-files (concat test-name "-files") "\\.m$" nil 
m-file)))
-      (t-utils-test-xr test-name m-files)))
-    "success")
+    (when (t-utils-is-treesit-available 'matlab test-name)
+      (let ((m-files (t-utils-get-files (concat test-name "-files") "\\.m\\'" 
nil
+                                        
test-matlab-ts-mode-on-save-fixes--file)))
+        (t-utils-test-xr test-name m-files)))))
 
 (provide 'test-matlab-ts-mode-on-save-fixes)
 ;;; test-matlab-ts-mode-on-save-fixes.el ends here
diff --git a/tests/test-matlab-ts-mode-outline.el 
b/tests/test-matlab-ts-mode-outline.el
index 18ce7f5574..e87f6b2bee 100644
--- a/tests/test-matlab-ts-mode-outline.el
+++ b/tests/test-matlab-ts-mode-outline.el
@@ -30,13 +30,21 @@
 (require 't-utils)
 (require 'matlab-ts-mode)
 
-(cl-defun test-matlab-ts-mode-outline (&optional m-file)
-  "Test defun movement using ./test-matlab-ts-mode-outline-files/NAME.m.
-Using ./test-matlab-ts-mode-outline-files/NAME.m, compare defun
-movement against
-./test-matlab-ts-mode-outline-files/NAME_expected.txt.  If M-FILE is
-not provided, loop comparing all
-./test-matlab-ts-mode-outline-files/NAME.m files.
+(defvar test-matlab-ts-mode-outline--file nil)
+
+(defun test-matlab-ts-mode-outline--file (m-file)
+  "Test an individual M-FILE.
+This is provided for debugging.
+  M-: (test-matlab-ts-mode-outline--file 
\"test-matlab-ts-mode-outline-files/M-FILE\")"
+  (let ((test-matlab-ts-mode-outline--file m-file))
+    (ert-run-tests-interactively "test-matlab-ts-mode-outline")))
+
+(ert-deftest test-matlab-ts-mode-outline ()
+  "Test outline mode using ./test-matlab-ts-mode-outline-files/NAME.m.
+Using ./test-matlab-ts-mode-outline-files/NAME.m, call 
`outline-search-function'
+and compare result agains
+./test-matlab-ts-mode-outline-files/NAME_expected.txt.  This loops
+on all ./test-matlab-ts-mode-outline-files/NAME.m files.
 
 To add a test, create
   ./test-matlab-ts-mode-outline-files/NAME.m
@@ -46,13 +54,10 @@ after validating it, rename it to
   ./test-matlab-ts-mode-outline-files/NAME_expected.txt"
 
   (let ((test-name "test-matlab-ts-mode-outline"))
-
-    (when (not (t-utils-is-treesit-available 'matlab test-name))
-      (cl-return-from test-matlab-ts-mode-outline))
-
-    (let ((m-files (t-utils-get-files (concat test-name "-files") "\\.m$" nil 
m-file)))
-      (t-utils-test-outline-search-function test-name m-files)))
-    "success")
+    (when (t-utils-is-treesit-available 'matlab test-name)
+      (let ((m-files (t-utils-get-files (concat test-name "-files") "\\.m\\'" 
nil
+                                        test-matlab-ts-mode-outline--file)))
+        (t-utils-test-outline-search-function test-name m-files)))))
 
 (provide 'test-matlab-ts-mode-outline)
 ;;; test-matlab-ts-mode-outline.el ends here
diff --git a/tests/test-matlab-ts-mode-page.el 
b/tests/test-matlab-ts-mode-page.el
index 989ca10f75..95a2f2adca 100644
--- a/tests/test-matlab-ts-mode-page.el
+++ b/tests/test-matlab-ts-mode-page.el
@@ -30,13 +30,21 @@
 (require 't-utils)
 (require 'matlab-ts-mode)
 
-(cl-defun test-matlab-ts-mode-page (&optional m-file)
-  "Test defun movement using ./test-matlab-ts-mode-page-files/NAME.m.
-Using ./test-matlab-ts-mode-page-files/NAME.m, compare comment
-keybindings against
-./test-matlab-ts-mode-page-files/NAME_expected.org.  If M-FILE is
-not provided, loop comparing all
-./test-matlab-ts-mode-page-files/NAME.m files.
+(defvar test-matlab-ts-mode-page--file nil)
+
+(defun test-matlab-ts-mode-page--file (m-file)
+  "Test an individual M-FILE.
+This is provided for debugging.
+  M-: (test-matlab-ts-mode-page--file 
\"test-matlab-ts-mode-page-files/M-FILE\")"
+  (let ((test-matlab-ts-mode-page--file m-file))
+    (ert-run-tests-interactively "test-matlab-ts-mode-page")))
+
+(ert-deftest test-matlab-ts-mode-page ()
+  "Test page movement using ./test-matlab-ts-mode-page-files/NAME.m.
+Using ./test-matlab-ts-mode-page-files/NAME.m, compare `forward-page'
+and `backward-page' against
+./test-matlab-ts-mode-page-files/NAME_expected.org.  This loops
+on all ./test-matlab-ts-mode-page-files/NAME.m files.
 
 To add a test, create
   ./test-matlab-ts-mode-page-files/NAME.m
@@ -46,13 +54,10 @@ after validating it, rename it to
   ./test-matlab-ts-mode-page-files/NAME_expected.org"
 
   (let ((test-name "test-matlab-ts-mode-page"))
-
-    (when (not (t-utils-is-treesit-available 'matlab test-name))
-      (cl-return-from test-matlab-ts-mode-page))
-
-    (let ((m-files (t-utils-get-files (concat test-name "-files") "\\.m$" nil 
m-file)))
-      (t-utils-test-xr test-name m-files)))
-    "success")
+    (when (t-utils-is-treesit-available 'matlab test-name)
+      (let ((m-files (t-utils-get-files (concat test-name "-files") "\\.m\\'" 
nil
+                                        test-matlab-ts-mode-page--file)))
+        (t-utils-test-xr test-name m-files)))))
 
 (provide 'test-matlab-ts-mode-page)
 ;;; test-matlab-ts-mode-page.el ends here
diff --git a/tests/test-matlab-ts-mode-show-paren-files/show_paren_string.m 
b/tests/test-matlab-ts-mode-show-paren-files/show_paren_string.m
index e6e994fa84..a19959c132 100644
--- a/tests/test-matlab-ts-mode-show-paren-files/show_paren_string.m
+++ b/tests/test-matlab-ts-mode-show-paren-files/show_paren_string.m
@@ -19,8 +19,7 @@ s3 = "<foo ' bar>";
 % (t-utils-xr (re-search-forward ">") (prin1 
(matlab-ts-mode--show-paren-or-block)))
 s4 = "<foo ' bar>";
 
-% (t-utils-xr (re-search-forward "<") "C-b" "C-b" (prin1 
(matlab-ts-mode--show-paren-or-block)))
-s5 = "<asdf
+% (t-utils-xr (re-search-forward "-end-quote") (kill-line) (re-search-backward 
"<") "C-b" (prin1 (matlab-ts-mode--show-paren-or-block)) "C-e" (insert 
(char-to-string 34)))
+s5 = "<asdf-end-quote"
 
-% (t-utils-xr (re-search-forward ">") (prin1 
(matlab-ts-mode--show-paren-or-block)))
-s6 = asdf>"
+% comment with a (") for s5.
diff --git 
a/tests/test-matlab-ts-mode-show-paren-files/show_paren_string_expected.org 
b/tests/test-matlab-ts-mode-show-paren-files/show_paren_string_expected.org
index 2f4561c21c..4e26ee4d80 100644
--- a/tests/test-matlab-ts-mode-show-paren-files/show_paren_string_expected.org
+++ b/tests/test-matlab-ts-mode-show-paren-files/show_paren_string_expected.org
@@ -180,50 +180,75 @@
 
 * Executing commands from show_paren_string.m:22:2:
 
-  (t-utils-xr (re-search-forward "<") "C-b" "C-b" (prin1 
(matlab-ts-mode--show-paren-or-block)))
+  (t-utils-xr (re-search-forward "-end-quote") (kill-line) (re-search-backward 
"<") "C-b" (prin1 (matlab-ts-mode--show-paren-or-block)) "C-e" (insert 
(char-to-string 34)))
 
-- Invoking      : (re-search-forward "<")
-  Start point   :  801
-  Moved to point:  809
-  : 23:7: s5 = "<asdf
-  :              ^
+- Invoking      : (re-search-forward "-end-quote")
+  Start point   :  876
+  Moved to point:  898
+  : 23:21: s5 = "<asdf-end-quote"
+  :                             ^
   No buffer modifications
 
-- Invoking      : "C-b" = backward-char
-  Start point   :  809
-  Moved to point:  808
-  : 23:6: s5 = "<asdf
+- Invoking      : (kill-line)
+  Start point   :  898
+  No point movement
+  Buffer modified:
+  #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -20,6 +20,6 @@
+ s4 = "<foo ' bar>";
+ 
+ % (t-utils-xr (re-search-forward "-end-quote") (kill-line) 
(re-search-backward "<") "C-b" (prin1 (matlab-ts-mode--show-paren-or-block)) 
"C-e" (insert (char-to-string 34)))
+-s5 = "<asdf-end-quote"
++s5 = "<asdf-end-quote
+ 
+ % comment with a (") for s5.
+  #+end_src diff
+
+- Invoking      : (re-search-backward "<")
+  Start point   :  898
+  Moved to point:  883
+  : 23:6: s5 = "<asdf-end-quote
   :             ^
   No buffer modifications
 
 - Invoking      : "C-b" = backward-char
-  Start point   :  808
-  Moved to point:  807
-  : 23:5: s5 = "<asdf
+  Start point   :  883
+  Moved to point:  882
+  : 23:5: s5 = "<asdf-end-quote
   :            ^
   No buffer modifications
 
 - Invoking      : (prin1 (matlab-ts-mode--show-paren-or-block))
-  Start point   :  807
+  Start point   :  882
   No point movement
   standard-output:
-    (807 808 nil nil t)
-  No buffer modifications
-
-* Executing commands from show_paren_string.m:25:2:
-
-  (t-utils-xr (re-search-forward ">") (prin1 
(matlab-ts-mode--show-paren-or-block)))
-
-- Invoking      : (re-search-forward ">")
-  Start point   :  899
-  Moved to point:  910
-  : 26:10: s6 = asdf>"
-  :                  ^
-  No buffer modifications
-
-- Invoking      : (prin1 (matlab-ts-mode--show-paren-or-block))
-  Start point   :  910
-  No point movement
-  standard-output:
-    (910 911 nil nil t)
-  No buffer modifications
+    (882 883 nil nil t)
+  No buffer modifications
+
+- Invoking      : "C-e" = move-end-of-line
+  Start point   :  882
+  Moved to point:  898
+  : 23:21: s5 = "<asdf-end-quote
+  :                             ^
+  No buffer modifications
+
+- Invoking      : (insert (char-to-string 34))
+  Start point   :  898
+  Moved to point:  899
+  : 23:22: s5 = "<asdf-end-quote"
+  :                              ^
+  Buffer modified:
+  #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -20,6 +20,6 @@
+ s4 = "<foo ' bar>";
+ 
+ % (t-utils-xr (re-search-forward "-end-quote") (kill-line) 
(re-search-backward "<") "C-b" (prin1 (matlab-ts-mode--show-paren-or-block)) 
"C-e" (insert (char-to-string 34)))
+-s5 = "<asdf-end-quote
++s5 = "<asdf-end-quote"
+ 
+ % comment with a (") for s5.
+  #+end_src diff
diff --git a/tests/test-matlab-ts-mode-show-paren.el 
b/tests/test-matlab-ts-mode-show-paren.el
index b5e5897cda..abb3246c53 100644
--- a/tests/test-matlab-ts-mode-show-paren.el
+++ b/tests/test-matlab-ts-mode-show-paren.el
@@ -30,10 +30,19 @@
 (require 't-utils)
 (require 'matlab-ts-mode)
 
-(cl-defun test-matlab-ts-mode-show-paren (&optional m-file)
-  "Test defun movement using ./test-matlab-ts-mode-show-paren-files/NAME.m.
-Using ./test-matlab-ts-mode-show-paren-files/NAME.m, compare defun
-movement against
+(defvar test-matlab-ts-mode-show-paren--file nil)
+
+(defun test-matlab-ts-mode-show-paren--file (m-file)
+  "Test an individual M-FILE.
+This is provided for debugging.
+  M-: (test-matlab-ts-mode-show-paren--file 
\"test-matlab-ts-mode-show-paren-files/M-FILE\")"
+  (let ((test-matlab-ts-mode-show-paren--file m-file))
+    (ert-run-tests-interactively "test-matlab-ts-mode-show-paren")))
+
+(ert-deftest test-matlab-ts-mode-show-paren ()
+  "Test show paren mode using ./test-matlab-ts-mode-show-paren-files/NAME.m.
+Using ./test-matlab-ts-mode-show-paren-files/NAME.m, result of
+`matlab-ts-mode--show-paren-or-block' for `show-paren-mode' against
 ./test-matlab-ts-mode-show-paren-files/NAME_expected.org.  If M-FILE is
 not provided, loop comparing all
 ./test-matlab-ts-mode-show-paren-files/NAME.m files.
@@ -46,13 +55,11 @@ after validating it, rename it to
   ./test-matlab-ts-mode-show-paren-files/NAME_expected.org"
 
   (let ((test-name "test-matlab-ts-mode-show-paren"))
+    (when (t-utils-is-treesit-available 'matlab test-name)
 
-    (when (not (t-utils-is-treesit-available 'matlab test-name))
-      (cl-return-from test-matlab-ts-mode-show-paren))
-
-    (let ((m-files (t-utils-get-files (concat test-name "-files") "\\.m$" nil 
m-file)))
-      (t-utils-test-xr test-name m-files)))
-    "success")
+      (let ((m-files (t-utils-get-files (concat test-name "-files") "\\.m\\'" 
nil
+                                        test-matlab-ts-mode-show-paren--file)))
+        (t-utils-test-xr test-name m-files)))))
 
 (provide 'test-matlab-ts-mode-show-paren)
 ;;; test-matlab-ts-mode-show-paren.el ends here
diff --git a/tests/test-matlab-ts-mode-syntax-table.el 
b/tests/test-matlab-ts-mode-syntax-table.el
index 569b56cd92..82d0ee5aef 100644
--- a/tests/test-matlab-ts-mode-syntax-table.el
+++ b/tests/test-matlab-ts-mode-syntax-table.el
@@ -28,13 +28,22 @@
 (require 't-utils)
 (require 'matlab-ts-mode)
 
-(cl-defun test-matlab-ts-mode-syntax-table (&optional m-file)
+(defvar test-matlab-ts-mode-syntax-table--file nil)
+
+(defun test-matlab-ts-mode-syntax-table--file (m-file)
+  "Test an individual M-FILE.
+This is provided for debugging.
+  M-: (test-matlab-ts-mode-syntax-table--file 
\"test-matlab-ts-mode-syntax-table-files/M-FILE\")"
+  (let ((test-matlab-ts-mode-syntax-table--file m-file))
+    (ert-run-tests-interactively "test-matlab-ts-mode-syntax-table")))
+
+(ert-deftest test-matlab-ts-mode-syntax-table ()
   "Test syntax-table using ./test-matlab-ts-mode-syntax-table-files/NAME.m.
 Compare ./test-matlab-ts-mode-syntax-table-files/NAME.m against
 ./test-matlab-ts-mode-syntax-table-files/NAME_expected.txt, where
-NAME_expected.txt gives the `syntax-ppss` value of each character in
-NAME.m.  If M-FILE is not provided, loop comparing all
-./test-matlab-ts-mode-indent-files/NAME.m files.
+NAME_expected.txt gives the `syntax-ppss' value of each character in
+NAME.m.  This loops on all ./test-matlab-ts-mode-syntax-table-files/NAME.m
+files.
 
 To add a test, create
   ./test-matlab-ts-mode-syntax-table-files/NAME.m
@@ -44,13 +53,10 @@ after validating it, rename it to
   ./test-matlab-ts-mode-syntax-table-files/NAME_expected.m"
 
   (let ((test-name "test-matlab-ts-mode-syntax-table"))
-    (when (not (t-utils-is-treesit-available 'matlab test-name))
-      (cl-return-from test-matlab-ts-mode-syntax-table))
-
-    (let ((m-files (t-utils-get-files (concat test-name "-files") "\\.m$" nil 
m-file)))
-      (t-utils-test-syntax-table test-name m-files)))
-
-  "success")
+    (when (t-utils-is-treesit-available 'matlab test-name)
+      (let ((m-files (t-utils-get-files (concat test-name "-files") "\\.m\\'" 
nil
+                                        
test-matlab-ts-mode-syntax-table--file)))
+        (t-utils-test-syntax-table test-name m-files)))))
 
 (provide 'test-matlab-ts-mode-syntax-table)
 ;;; test-matlab-ts-mode-syntax-table.el ends here
diff --git a/tests/test-matlab-ts-mode-thing-settings.el 
b/tests/test-matlab-ts-mode-thing-settings.el
index 3e63072a14..ae1c05a8ea 100644
--- a/tests/test-matlab-ts-mode-thing-settings.el
+++ b/tests/test-matlab-ts-mode-thing-settings.el
@@ -30,13 +30,22 @@
 (require 't-utils)
 (require 'matlab-ts-mode)
 
-(cl-defun test-matlab-ts-mode-thing-settings (&optional m-file)
-  "Test defun movement using ./test-matlab-ts-mode-thing-settings-files/NAME.m.
-Using ./test-matlab-ts-mode-thing-settings-files/NAME.m, compare defun
-movement against
-./test-matlab-ts-mode-thing-settings-files/NAME_expected.org.  If M-FILE is
-not provided, loop comparing all
-./test-matlab-ts-mode-thing-settings-files/NAME.m files.
+(defvar test-matlab-ts-mode-thing-settings--file nil)
+
+(defun test-matlab-ts-mode-thing-settings--file (m-file)
+  "Test an individual M-FILE.
+This is provided for debugging.
+  M-: (test-matlab-ts-mode-thing-settings--file
+      \"test-matlab-ts-mode-thing-settings-files/M-FILE\")"
+  (let ((test-matlab-ts-mode-thing-settings--file m-file))
+    (ert-run-tests-interactively "test-matlab-ts-mode-thing-settings")))
+
+(ert-deftest test-matlab-ts-mode-thing-settings ()
+  "Test thing settings using ./test-matlab-ts-mode-thing-settings-files/NAME.m.
+Using ./test-matlab-ts-mode-thing-settings-files/NAME.m, compare
+movement commands, e.g. `forward-sentace' that use treesit thing
+settings.  ./test-matlab-ts-mode-thing-settings-files/NAME_expected.org.
+This loops on all ./test-matlab-ts-mode-thing-settings-files/NAME.m files.
 
 To add a test, create
   ./test-matlab-ts-mode-thing-settings-files/NAME.m
@@ -46,13 +55,10 @@ after validating it, rename it to
   ./test-matlab-ts-mode-thing-settings-files/NAME_expected.org"
 
   (let ((test-name "test-matlab-ts-mode-thing-settings"))
-
-    (when (not (t-utils-is-treesit-available 'matlab test-name))
-      (cl-return-from test-matlab-ts-mode-thing-settings))
-
-    (let ((m-files (t-utils-get-files (concat test-name "-files") "\\.m$" nil 
m-file)))
-      (t-utils-test-xr test-name m-files)))
-    "success")
+    (when (t-utils-is-treesit-available 'matlab test-name)
+      (let ((m-files (t-utils-get-files (concat test-name "-files") "\\.m\\'" 
nil
+                                        
test-matlab-ts-mode-thing-settings--file)))
+        (t-utils-test-xr test-name m-files)))))
 
 (provide 'test-matlab-ts-mode-thing-settings)
 ;;; test-matlab-ts-mode-thing-settings.el ends here
diff --git a/tests/test-matlab-ts-mode-treesit-defun-name.el 
b/tests/test-matlab-ts-mode-treesit-defun-name.el
index 90830a746d..8af291c7d7 100644
--- a/tests/test-matlab-ts-mode-treesit-defun-name.el
+++ b/tests/test-matlab-ts-mode-treesit-defun-name.el
@@ -30,13 +30,22 @@
 (require 't-utils)
 (require 'matlab-ts-mode)
 
-(cl-defun test-matlab-ts-mode-treesit-defun-name (&optional m-file)
-  "Test defun movement using 
./test-matlab-ts-mode-treesit-defun-name-files/NAME.m.
+(defvar test-matlab-ts-mode-treesit-defun-name--file nil)
+
+(defun test-matlab-ts-mode-treesit-defun-name--file (m-file)
+  "Test an individual M-FILE.
+This is provided for debugging.
+  M-: (test-matlab-ts-mode-treesit-defun-name--file
+      \"test-matlab-ts-mode-treesit-defun-name-files/M-FILE\")"
+  (let ((test-matlab-ts-mode-treesit-defun-name--file m-file))
+    (ert-run-tests-interactively "test-matlab-ts-mode-treesit-defun-name")))
+
+(ert-deftest test-matlab-ts-mode-treesit-defun-name ()
+  "Test defun setup using 
./test-matlab-ts-mode-treesit-defun-name-files/NAME.m.
 Using ./test-matlab-ts-mode-treesit-defun-name-files/NAME.m, compare defun
-movement against
-./test-matlab-ts-mode-treesit-defun-name-files/NAME_expected.txt.  If M-FILE is
-not provided, loop comparing all
-./test-matlab-ts-mode-treesit-defun-name-files/NAME.m files.
+setup against
+./test-matlab-ts-mode-treesit-defun-name-files/NAME_expected.txt.  This loops
+on all ./test-matlab-ts-mode-treesit-defun-name-files/NAME.m files.
 
 To add a test, create
   ./test-matlab-ts-mode-treesit-defun-name-files/NAME.m
@@ -46,13 +55,10 @@ after validating it, rename it to
   ./test-matlab-ts-mode-treesit-defun-name-files/NAME_expected.txt"
 
   (let ((test-name "test-matlab-ts-mode-treesit-defun-name"))
-
-    (when (not (t-utils-is-treesit-available 'matlab test-name))
-      (cl-return-from test-matlab-ts-mode-defun-name))
-
-    (let ((m-files (t-utils-get-files (concat test-name "-files") "\\.m$" nil 
m-file)))
-      (t-utils-test-treesit-defun-name test-name m-files)))
-    "success")
+    (when (t-utils-is-treesit-available 'matlab test-name)
+      (let ((m-files (t-utils-get-files (concat test-name "-files") "\\.m\\'" 
nil
+                                        
test-matlab-ts-mode-treesit-defun-name--file)))
+        (t-utils-test-treesit-defun-name test-name m-files)))))
 
 (provide 'test-matlab-ts-mode-treesit-defun-name)
 ;;; test-matlab-ts-mode-treesit-defun-name.el ends here

Reply via email to