emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 62f7760e619 1/3: Add `skip-when` macro to `ert-deftest`


From: Stefan Kangas
Subject: master 62f7760e619 1/3: Add `skip-when` macro to `ert-deftest`
Date: Mon, 4 Sep 2023 12:25:38 -0400 (EDT)

branch: master
commit 62f7760e61900b6ac0fb513294129130446b17e7
Author: Stefan Kangas <stefankangas@gmail.com>
Commit: Stefan Kangas <stefankangas@gmail.com>

    Add `skip-when` macro to `ert-deftest`
    
    This can help avoid some awkward test skip conditions.
    
    For example, this triple negation:
        (skip-unless (not noninteractive))
    
    Can be written as the simpler:
        (skip-when noninteractive)
    
    * lisp/emacs-lisp/ert.el (ert-deftest): Add new 'skip-when' macro.
    (ert--skip-when): New internal function.
    * doc/misc/ert.texi (Tests and Their Environment): Document above
    new macro.
    * test/lisp/emacs-lisp/ert-tests.el (ert-test-skip-when): New test.
---
 doc/misc/ert.texi                 | 23 +++++++++++++++++++++--
 etc/NEWS                          |  7 +++++++
 lisp/emacs-lisp/ert.el            | 39 +++++++++++++++++++++++++--------------
 test/lisp/emacs-lisp/ert-tests.el | 14 ++++++++++++++
 4 files changed, 67 insertions(+), 16 deletions(-)

diff --git a/doc/misc/ert.texi b/doc/misc/ert.texi
index a6b62a058f2..f4a072cf2bc 100644
--- a/doc/misc/ert.texi
+++ b/doc/misc/ert.texi
@@ -658,11 +658,30 @@ versions, specific architectures, etc.:
 @cindex skipping tests
 @cindex test preconditions
 @cindex preconditions of a test
+@findex skip-when
+@findex skip-unless
 Sometimes, it doesn't make sense to run a test due to missing
 preconditions.  A required Emacs feature might not be compiled in, the
 function to be tested could call an external binary which might not be
-available on the test machine, you name it.  In this case, the macro
-@code{skip-unless} could be used to skip the test:
+available on the test machine, you name it.  In this case, the macros
+@code{skip-when} or @code{skip-unless} could be used to skip the
+test.@footnote{The @code{skip-when} macro was added in Emacs 30.1.  If
+you need your tests to be compatible with older versions of Emacs, use
+@code{skip-unless} instead.}
+
+@noindent
+For example, this test is skipped on MS-Windows and macOS:
+
+@lisp
+(ert-deftest test-gnu-linux ()
+  "A test that is not relevant on MS-Windows and macOS."
+  (skip-when (memq system-type '(windows-nt ns))
+  ...))
+@end lisp
+
+@noindent
+This test is skipped if the feature @samp{dbusbind} is not present in
+the running Emacs:
 
 @lisp
 (ert-deftest test-dbus ()
diff --git a/etc/NEWS b/etc/NEWS
index 3afb0e3008e..936bb62d750 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -724,6 +724,13 @@ without specifying a file, like this:
 *** New user option 'image-dired-thumb-naming'.
 You can now configure how a thumbnail is named using this option.
 
+** ERT
+
+*** New macro `skip-when' to skip 'ert-deftest' tests.
+This can help avoid some awkward skip conditions.  For example
+'(skip-unless (not noninteractive))' can be changed to the easier
+to read '(skip-when noninteractive)'.
+
 ** checkdoc
 
 ---
diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el
index 4ea894f4ede..d727bc94ec5 100644
--- a/lisp/emacs-lisp/ert.el
+++ b/lisp/emacs-lisp/ert.el
@@ -34,17 +34,18 @@
 ;; `ert-run-tests-batch-and-exit' for non-interactive use.
 ;;
 ;; The body of `ert-deftest' forms resembles a function body, but the
-;; additional operators `should', `should-not', `should-error' and
-;; `skip-unless' are available.  `should' is similar to cl's `assert',
-;; but signals a different error when its condition is violated that
-;; is caught and processed by ERT.  In addition, it analyzes its
-;; argument form and records information that helps debugging
-;; (`cl-assert' tries to do something similar when its second argument
-;; SHOW-ARGS is true, but `should' is more sophisticated).  For
-;; information on `should-not' and `should-error', see their
-;; docstrings.  `skip-unless' skips the test immediately without
-;; processing further, this is useful for checking the test
-;; environment (like availability of features, external binaries, etc).
+;; additional operators `should', `should-not', `should-error',
+;; `skip-when' and `skip-unless' are available.  `should' is similar
+;; to cl's `assert', but signals a different error when its condition
+;; is violated that is caught and processed by ERT.  In addition, it
+;; analyzes its argument form and records information that helps
+;; debugging (`cl-assert' tries to do something similar when its
+;; second argument SHOW-ARGS is true, but `should' is more
+;; sophisticated).  For information on `should-not' and
+;; `should-error', see their docstrings.  The `skip-when' and
+;; `skip-unless' forms skip the test immediately, which is useful for
+;; checking the test environment (like availability of features,
+;; external binaries, etc).
 ;;
 ;; See ERT's Info manual `(ert) Top' as well as the docstrings for
 ;; more details.  To see some examples of tests written in ERT, see
@@ -194,8 +195,8 @@ and the body."
 BODY is evaluated as a `progn' when the test is run.  It should
 signal a condition on failure or just return if the test passes.
 
-`should', `should-not', `should-error' and `skip-unless' are
-useful for assertions in BODY.
+`should', `should-not', `should-error', `skip-when', and
+`skip-unless' are useful for assertions in BODY.
 
 Use `ert' to run tests interactively.
 
@@ -227,7 +228,8 @@ in batch mode, an error is signaled.
                (tags nil tags-supplied-p))
          body)
         (ert--parse-keys-and-body docstring-keys-and-body)
-      `(cl-macrolet ((skip-unless (form) `(ert--skip-unless ,form)))
+      `(cl-macrolet ((skip-when (form) `(ert--skip-when ,form))
+                     (skip-unless (form) `(ert--skip-unless ,form)))
          (ert-set-test ',name
                        (make-ert-test
                         :name ',name
@@ -464,6 +466,15 @@ failed."
                        (list
                         :fail-reason "did not signal an error")))))))))
 
+(cl-defmacro ert--skip-when (form)
+  "Evaluate FORM.  If it returns t, skip the current test.
+Errors during evaluation are caught and handled like t."
+  (declare (debug t))
+  (ert--expand-should `(skip-when ,form) form
+                      (lambda (inner-form form-description-form _value-var)
+                        `(when (condition-case nil ,inner-form (t t))
+                           (ert-skip ,form-description-form)))))
+
 (cl-defmacro ert--skip-unless (form)
   "Evaluate FORM.  If it returns nil, skip the current test.
 Errors during evaluation are caught and handled like nil."
diff --git a/test/lisp/emacs-lisp/ert-tests.el 
b/test/lisp/emacs-lisp/ert-tests.el
index 7713a0f6e38..bb3de111e3e 100644
--- a/test/lisp/emacs-lisp/ert-tests.el
+++ b/test/lisp/emacs-lisp/ert-tests.el
@@ -304,6 +304,20 @@ failed or if there was a problem."
   (cl-macrolet ((test () (error "Foo")))
     (should-error (test))))
 
+(ert-deftest ert-test-skip-when ()
+  ;; Don't skip.
+  (let ((test (make-ert-test :body (lambda () (skip-when nil)))))
+    (let ((result (ert-run-test test)))
+      (should (ert-test-passed-p result))))
+  ;; Skip.
+  (let ((test (make-ert-test :body (lambda () (skip-when t)))))
+    (let ((result (ert-run-test test)))
+      (should (ert-test-skipped-p result))))
+  ;; Skip in case of error.
+  (let ((test (make-ert-test :body (lambda () (skip-when (error "Foo"))))))
+    (let ((result (ert-run-test test)))
+      (should (ert-test-skipped-p result)))))
+
 (ert-deftest ert-test-skip-unless ()
   ;; Don't skip.
   (let ((test (make-ert-test :body (lambda () (skip-unless t)))))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]