mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2025-02-01 20:06:00 +00:00
950 lines
41 KiB
EmacsLisp
950 lines
41 KiB
EmacsLisp
;;; ert-tests.el --- ERT's self-tests
|
|
|
|
;; Copyright (C) 2007-2008, 2010-2011 Free Software Foundation, Inc.
|
|
|
|
;; Author: Christian Ohler <ohler@gnu.org>
|
|
|
|
;; This file is part of GNU Emacs.
|
|
|
|
;; 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 of the
|
|
;; License, 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 this program. If not, see `http://www.gnu.org/licenses/'.
|
|
|
|
;;; Commentary:
|
|
|
|
;; This file is part of ERT, the Emacs Lisp Regression Testing tool.
|
|
;; See ert.el or the texinfo manual for more details.
|
|
|
|
;;; Code:
|
|
|
|
(eval-when-compile
|
|
(require 'cl))
|
|
(require 'ert)
|
|
|
|
|
|
;;; Self-test that doesn't rely on ERT, for bootstrapping.
|
|
|
|
;; This is used to test that bodies actually run.
|
|
(defvar ert--test-body-was-run)
|
|
(ert-deftest ert-test-body-runs ()
|
|
(setq ert--test-body-was-run t))
|
|
|
|
(defun ert-self-test ()
|
|
"Run ERT's self-tests and make sure they actually ran."
|
|
(let ((window-configuration (current-window-configuration)))
|
|
(let ((ert--test-body-was-run nil))
|
|
;; The buffer name chosen here should not compete with the default
|
|
;; results buffer name for completion in `switch-to-buffer'.
|
|
(let ((stats (ert-run-tests-interactively "^ert-" " *ert self-tests*")))
|
|
(assert ert--test-body-was-run)
|
|
(if (zerop (ert-stats-completed-unexpected stats))
|
|
;; Hide results window only when everything went well.
|
|
(set-window-configuration window-configuration)
|
|
(error "ERT self-test failed"))))))
|
|
|
|
(defun ert-self-test-and-exit ()
|
|
"Run ERT's self-tests and exit Emacs.
|
|
|
|
The exit code will be zero if the tests passed, nonzero if they
|
|
failed or if there was a problem."
|
|
(unwind-protect
|
|
(progn
|
|
(ert-self-test)
|
|
(kill-emacs 0))
|
|
(unwind-protect
|
|
(progn
|
|
(message "Error running tests")
|
|
(backtrace))
|
|
(kill-emacs 1))))
|
|
|
|
|
|
;;; Further tests are defined using ERT.
|
|
|
|
(ert-deftest ert-test-nested-test-body-runs ()
|
|
"Test that nested test bodies run."
|
|
(lexical-let ((was-run nil))
|
|
(let ((test (make-ert-test :body (lambda ()
|
|
(setq was-run t)))))
|
|
(assert (not was-run))
|
|
(ert-run-test test)
|
|
(assert was-run))))
|
|
|
|
|
|
;;; Test that pass/fail works.
|
|
(ert-deftest ert-test-pass ()
|
|
(let ((test (make-ert-test :body (lambda ()))))
|
|
(let ((result (ert-run-test test)))
|
|
(assert (ert-test-passed-p result)))))
|
|
|
|
(ert-deftest ert-test-fail ()
|
|
(let ((test (make-ert-test :body (lambda () (ert-fail "failure message")))))
|
|
(let ((result (let ((ert-debug-on-error nil))
|
|
(ert-run-test test))))
|
|
(assert (ert-test-failed-p result) t)
|
|
(assert (equal (ert-test-result-with-condition-condition result)
|
|
'(ert-test-failed "failure message"))
|
|
t))))
|
|
|
|
(ert-deftest ert-test-fail-debug-with-condition-case ()
|
|
(let ((test (make-ert-test :body (lambda () (ert-fail "failure message")))))
|
|
(condition-case condition
|
|
(progn
|
|
(let ((ert-debug-on-error t))
|
|
(ert-run-test test))
|
|
(assert nil))
|
|
((error)
|
|
(assert (equal condition '(ert-test-failed "failure message")) t)))))
|
|
|
|
(ert-deftest ert-test-fail-debug-with-debugger-1 ()
|
|
(let ((test (make-ert-test :body (lambda () (ert-fail "failure message")))))
|
|
(let ((debugger (lambda (&rest debugger-args)
|
|
(assert nil))))
|
|
(let ((ert-debug-on-error nil))
|
|
(ert-run-test test)))))
|
|
|
|
(ert-deftest ert-test-fail-debug-with-debugger-2 ()
|
|
(let ((test (make-ert-test :body (lambda () (ert-fail "failure message")))))
|
|
(block nil
|
|
(let ((debugger (lambda (&rest debugger-args)
|
|
(return-from nil nil))))
|
|
(let ((ert-debug-on-error t))
|
|
(ert-run-test test))
|
|
(assert nil)))))
|
|
|
|
(ert-deftest ert-test-fail-debug-nested-with-debugger ()
|
|
(let ((test (make-ert-test :body (lambda ()
|
|
(let ((ert-debug-on-error t))
|
|
(ert-fail "failure message"))))))
|
|
(let ((debugger (lambda (&rest debugger-args)
|
|
(assert nil nil "Assertion a"))))
|
|
(let ((ert-debug-on-error nil))
|
|
(ert-run-test test))))
|
|
(let ((test (make-ert-test :body (lambda ()
|
|
(let ((ert-debug-on-error nil))
|
|
(ert-fail "failure message"))))))
|
|
(block nil
|
|
(let ((debugger (lambda (&rest debugger-args)
|
|
(return-from nil nil))))
|
|
(let ((ert-debug-on-error t))
|
|
(ert-run-test test))
|
|
(assert nil nil "Assertion b")))))
|
|
|
|
(ert-deftest ert-test-error ()
|
|
(let ((test (make-ert-test :body (lambda () (error "Error message")))))
|
|
(let ((result (let ((ert-debug-on-error nil))
|
|
(ert-run-test test))))
|
|
(assert (ert-test-failed-p result) t)
|
|
(assert (equal (ert-test-result-with-condition-condition result)
|
|
'(error "Error message"))
|
|
t))))
|
|
|
|
(ert-deftest ert-test-error-debug ()
|
|
(let ((test (make-ert-test :body (lambda () (error "Error message")))))
|
|
(condition-case condition
|
|
(progn
|
|
(let ((ert-debug-on-error t))
|
|
(ert-run-test test))
|
|
(assert nil))
|
|
((error)
|
|
(assert (equal condition '(error "Error message")) t)))))
|
|
|
|
|
|
;;; Test that `should' works.
|
|
(ert-deftest ert-test-should ()
|
|
(let ((test (make-ert-test :body (lambda () (should nil)))))
|
|
(let ((result (let ((ert-debug-on-error nil))
|
|
(ert-run-test test))))
|
|
(assert (ert-test-failed-p result) t)
|
|
(assert (equal (ert-test-result-with-condition-condition result)
|
|
'(ert-test-failed ((should nil) :form nil :value nil)))
|
|
t)))
|
|
(let ((test (make-ert-test :body (lambda () (should t)))))
|
|
(let ((result (ert-run-test test)))
|
|
(assert (ert-test-passed-p result) t))))
|
|
|
|
(ert-deftest ert-test-should-value ()
|
|
(should (eql (should 'foo) 'foo))
|
|
(should (eql (should 'bar) 'bar)))
|
|
|
|
(ert-deftest ert-test-should-not ()
|
|
(let ((test (make-ert-test :body (lambda () (should-not t)))))
|
|
(let ((result (let ((ert-debug-on-error nil))
|
|
(ert-run-test test))))
|
|
(assert (ert-test-failed-p result) t)
|
|
(assert (equal (ert-test-result-with-condition-condition result)
|
|
'(ert-test-failed ((should-not t) :form t :value t)))
|
|
t)))
|
|
(let ((test (make-ert-test :body (lambda () (should-not nil)))))
|
|
(let ((result (ert-run-test test)))
|
|
(assert (ert-test-passed-p result)))))
|
|
|
|
(ert-deftest ert-test-should-with-macrolet ()
|
|
(let ((test (make-ert-test :body (lambda ()
|
|
(macrolet ((foo () `(progn t nil)))
|
|
(should (foo)))))))
|
|
(let ((result (let ((ert-debug-on-error nil))
|
|
(ert-run-test test))))
|
|
(should (ert-test-failed-p result))
|
|
(should (equal
|
|
(ert-test-result-with-condition-condition result)
|
|
'(ert-test-failed ((should (foo))
|
|
:form (progn t nil)
|
|
:value nil)))))))
|
|
|
|
(ert-deftest ert-test-should-error ()
|
|
;; No error.
|
|
(let ((test (make-ert-test :body (lambda () (should-error (progn))))))
|
|
(let ((result (let ((ert-debug-on-error nil))
|
|
(ert-run-test test))))
|
|
(should (ert-test-failed-p result))
|
|
(should (equal (ert-test-result-with-condition-condition result)
|
|
'(ert-test-failed
|
|
((should-error (progn))
|
|
:form (progn)
|
|
:value nil
|
|
:fail-reason "did not signal an error"))))))
|
|
;; A simple error.
|
|
(should (equal (should-error (error "Foo"))
|
|
'(error "Foo")))
|
|
;; Error of unexpected type.
|
|
(let ((test (make-ert-test :body (lambda ()
|
|
(should-error (error "Foo")
|
|
:type 'singularity-error)))))
|
|
(let ((result (ert-run-test test)))
|
|
(should (ert-test-failed-p result))
|
|
(should (equal
|
|
(ert-test-result-with-condition-condition result)
|
|
'(ert-test-failed
|
|
((should-error (error "Foo") :type 'singularity-error)
|
|
:form (error "Foo")
|
|
:condition (error "Foo")
|
|
:fail-reason
|
|
"the error signalled did not have the expected type"))))))
|
|
;; Error of the expected type.
|
|
(let* ((error nil)
|
|
(test (make-ert-test
|
|
:body (lambda ()
|
|
(setq error
|
|
(should-error (signal 'singularity-error nil)
|
|
:type 'singularity-error))))))
|
|
(let ((result (ert-run-test test)))
|
|
(should (ert-test-passed-p result))
|
|
(should (equal error '(singularity-error))))))
|
|
|
|
(ert-deftest ert-test-should-error-subtypes ()
|
|
(should-error (signal 'singularity-error nil)
|
|
:type 'singularity-error
|
|
:exclude-subtypes t)
|
|
(let ((test (make-ert-test
|
|
:body (lambda ()
|
|
(should-error (signal 'arith-error nil)
|
|
:type 'singularity-error)))))
|
|
(let ((result (ert-run-test test)))
|
|
(should (ert-test-failed-p result))
|
|
(should (equal
|
|
(ert-test-result-with-condition-condition result)
|
|
'(ert-test-failed
|
|
((should-error (signal 'arith-error nil)
|
|
:type 'singularity-error)
|
|
:form (signal arith-error nil)
|
|
:condition (arith-error)
|
|
:fail-reason
|
|
"the error signalled did not have the expected type"))))))
|
|
(let ((test (make-ert-test
|
|
:body (lambda ()
|
|
(should-error (signal 'arith-error nil)
|
|
:type 'singularity-error
|
|
:exclude-subtypes t)))))
|
|
(let ((result (ert-run-test test)))
|
|
(should (ert-test-failed-p result))
|
|
(should (equal
|
|
(ert-test-result-with-condition-condition result)
|
|
'(ert-test-failed
|
|
((should-error (signal 'arith-error nil)
|
|
:type 'singularity-error
|
|
:exclude-subtypes t)
|
|
:form (signal arith-error nil)
|
|
:condition (arith-error)
|
|
:fail-reason
|
|
"the error signalled did not have the expected type"))))))
|
|
(let ((test (make-ert-test
|
|
:body (lambda ()
|
|
(should-error (signal 'singularity-error nil)
|
|
:type 'arith-error
|
|
:exclude-subtypes t)))))
|
|
(let ((result (ert-run-test test)))
|
|
(should (ert-test-failed-p result))
|
|
(should (equal
|
|
(ert-test-result-with-condition-condition result)
|
|
'(ert-test-failed
|
|
((should-error (signal 'singularity-error nil)
|
|
:type 'arith-error
|
|
:exclude-subtypes t)
|
|
:form (signal singularity-error nil)
|
|
:condition (singularity-error)
|
|
:fail-reason
|
|
"the error signalled was a subtype of the expected type")))))
|
|
))
|
|
|
|
(defmacro ert--test-my-list (&rest args)
|
|
"Don't use this. Instead, call `list' with ARGS, it does the same thing.
|
|
|
|
This macro is used to test if macroexpansion in `should' works."
|
|
`(list ,@args))
|
|
|
|
(ert-deftest ert-test-should-failure-debugging ()
|
|
"Test that `should' errors contain the information we expect them to."
|
|
(loop for (body expected-condition) in
|
|
`((,(lambda () (let ((x nil)) (should x)))
|
|
(ert-test-failed ((should x) :form x :value nil)))
|
|
(,(lambda () (let ((x t)) (should-not x)))
|
|
(ert-test-failed ((should-not x) :form x :value t)))
|
|
(,(lambda () (let ((x t)) (should (not x))))
|
|
(ert-test-failed ((should (not x)) :form (not t) :value nil)))
|
|
(,(lambda () (let ((x nil)) (should-not (not x))))
|
|
(ert-test-failed ((should-not (not x)) :form (not nil) :value t)))
|
|
(,(lambda () (let ((x t) (y nil)) (should-not
|
|
(ert--test-my-list x y))))
|
|
(ert-test-failed
|
|
((should-not (ert--test-my-list x y))
|
|
:form (list t nil)
|
|
:value (t nil))))
|
|
(,(lambda () (let ((x t)) (should (error "Foo"))))
|
|
(error "Foo")))
|
|
do
|
|
(let ((test (make-ert-test :body body)))
|
|
(condition-case actual-condition
|
|
(progn
|
|
(let ((ert-debug-on-error t))
|
|
(ert-run-test test))
|
|
(assert nil))
|
|
((error)
|
|
(should (equal actual-condition expected-condition)))))))
|
|
|
|
(ert-deftest ert-test-deftest ()
|
|
(should (equal (macroexpand '(ert-deftest abc () "foo" :tags '(bar)))
|
|
'(progn
|
|
(ert-set-test 'abc
|
|
(make-ert-test :name 'abc
|
|
:documentation "foo"
|
|
:tags '(bar)
|
|
:body (lambda ())))
|
|
(push '(ert-deftest . abc) current-load-list)
|
|
'abc)))
|
|
(should (equal (macroexpand '(ert-deftest def ()
|
|
:expected-result ':passed))
|
|
'(progn
|
|
(ert-set-test 'def
|
|
(make-ert-test :name 'def
|
|
:expected-result-type ':passed
|
|
:body (lambda ())))
|
|
(push '(ert-deftest . def) current-load-list)
|
|
'def)))
|
|
;; :documentation keyword is forbidden
|
|
(should-error (macroexpand '(ert-deftest ghi ()
|
|
:documentation "foo"))))
|
|
|
|
(ert-deftest ert-test-record-backtrace ()
|
|
(let ((test (make-ert-test :body (lambda () (ert-fail "foo")))))
|
|
(let ((result (ert-run-test test)))
|
|
(should (ert-test-failed-p result))
|
|
(with-temp-buffer
|
|
(ert--print-backtrace (ert-test-failed-backtrace result))
|
|
(goto-char (point-min))
|
|
(end-of-line)
|
|
(let ((first-line (buffer-substring-no-properties (point-min) (point))))
|
|
(should (equal first-line " signal(ert-test-failed (\"foo\"))")))))))
|
|
|
|
(ert-deftest ert-test-messages ()
|
|
:tags '(:causes-redisplay)
|
|
(let* ((message-string "Test message")
|
|
(messages-buffer (get-buffer-create "*Messages*"))
|
|
(test (make-ert-test :body (lambda () (message "%s" message-string)))))
|
|
(with-current-buffer messages-buffer
|
|
(let ((result (ert-run-test test)))
|
|
(should (equal (concat message-string "\n")
|
|
(ert-test-result-messages result)))))))
|
|
|
|
(ert-deftest ert-test-running-tests ()
|
|
(let ((outer-test (ert-get-test 'ert-test-running-tests)))
|
|
(should (equal (ert-running-test) outer-test))
|
|
(let (test1 test2 test3)
|
|
(setq test1 (make-ert-test
|
|
:name "1"
|
|
:body (lambda ()
|
|
(should (equal (ert-running-test) outer-test))
|
|
(should (equal ert--running-tests
|
|
(list test1 test2 test3
|
|
outer-test)))))
|
|
test2 (make-ert-test
|
|
:name "2"
|
|
:body (lambda ()
|
|
(should (equal (ert-running-test) outer-test))
|
|
(should (equal ert--running-tests
|
|
(list test3 test2 outer-test)))
|
|
(ert-run-test test1)))
|
|
test3 (make-ert-test
|
|
:name "3"
|
|
:body (lambda ()
|
|
(should (equal (ert-running-test) outer-test))
|
|
(should (equal ert--running-tests
|
|
(list test3 outer-test)))
|
|
(ert-run-test test2))))
|
|
(should (ert-test-passed-p (ert-run-test test3))))))
|
|
|
|
(ert-deftest ert-test-test-result-expected-p ()
|
|
"Test `ert-test-result-expected-p' and (implicitly) `ert-test-result-type-p'."
|
|
;; passing test
|
|
(let ((test (make-ert-test :body (lambda ()))))
|
|
(should (ert-test-result-expected-p test (ert-run-test test))))
|
|
;; unexpected failure
|
|
(let ((test (make-ert-test :body (lambda () (ert-fail "failed")))))
|
|
(should-not (ert-test-result-expected-p test (ert-run-test test))))
|
|
;; expected failure
|
|
(let ((test (make-ert-test :body (lambda () (ert-fail "failed"))
|
|
:expected-result-type ':failed)))
|
|
(should (ert-test-result-expected-p test (ert-run-test test))))
|
|
;; `not' expected type
|
|
(let ((test (make-ert-test :body (lambda ())
|
|
:expected-result-type '(not :failed))))
|
|
(should (ert-test-result-expected-p test (ert-run-test test))))
|
|
(let ((test (make-ert-test :body (lambda ())
|
|
:expected-result-type '(not :passed))))
|
|
(should-not (ert-test-result-expected-p test (ert-run-test test))))
|
|
;; `and' expected type
|
|
(let ((test (make-ert-test :body (lambda ())
|
|
:expected-result-type '(and :passed :failed))))
|
|
(should-not (ert-test-result-expected-p test (ert-run-test test))))
|
|
(let ((test (make-ert-test :body (lambda ())
|
|
:expected-result-type '(and :passed
|
|
(not :failed)))))
|
|
(should (ert-test-result-expected-p test (ert-run-test test))))
|
|
;; `or' expected type
|
|
(let ((test (make-ert-test :body (lambda ())
|
|
:expected-result-type '(or (and :passed :failed)
|
|
:passed))))
|
|
(should (ert-test-result-expected-p test (ert-run-test test))))
|
|
(let ((test (make-ert-test :body (lambda ())
|
|
:expected-result-type '(or (and :passed :failed)
|
|
nil (not t)))))
|
|
(should-not (ert-test-result-expected-p test (ert-run-test test)))))
|
|
|
|
;;; Test `ert-select-tests'.
|
|
(ert-deftest ert-test-select-regexp ()
|
|
(should (equal (ert-select-tests "^ert-test-select-regexp$" t)
|
|
(list (ert-get-test 'ert-test-select-regexp)))))
|
|
|
|
(ert-deftest ert-test-test-boundp ()
|
|
(should (ert-test-boundp 'ert-test-test-boundp))
|
|
(should-not (ert-test-boundp (make-symbol "ert-not-a-test"))))
|
|
|
|
(ert-deftest ert-test-select-member ()
|
|
(should (equal (ert-select-tests '(member ert-test-select-member) t)
|
|
(list (ert-get-test 'ert-test-select-member)))))
|
|
|
|
(ert-deftest ert-test-select-test ()
|
|
(should (equal (ert-select-tests (ert-get-test 'ert-test-select-test) t)
|
|
(list (ert-get-test 'ert-test-select-test)))))
|
|
|
|
(ert-deftest ert-test-select-symbol ()
|
|
(should (equal (ert-select-tests 'ert-test-select-symbol t)
|
|
(list (ert-get-test 'ert-test-select-symbol)))))
|
|
|
|
(ert-deftest ert-test-select-and ()
|
|
(let ((test (make-ert-test
|
|
:name nil
|
|
:body nil
|
|
:most-recent-result (make-ert-test-failed
|
|
:condition nil
|
|
:backtrace nil
|
|
:infos nil))))
|
|
(should (equal (ert-select-tests `(and (member ,test) :failed) t)
|
|
(list test)))))
|
|
|
|
(ert-deftest ert-test-select-tag ()
|
|
(let ((test (make-ert-test
|
|
:name nil
|
|
:body nil
|
|
:tags '(a b))))
|
|
(should (equal (ert-select-tests `(tag a) (list test)) (list test)))
|
|
(should (equal (ert-select-tests `(tag b) (list test)) (list test)))
|
|
(should (equal (ert-select-tests `(tag c) (list test)) '()))))
|
|
|
|
|
|
;;; Tests for utility functions.
|
|
(ert-deftest ert-test-proper-list-p ()
|
|
(should (ert--proper-list-p '()))
|
|
(should (ert--proper-list-p '(1)))
|
|
(should (ert--proper-list-p '(1 2)))
|
|
(should (ert--proper-list-p '(1 2 3)))
|
|
(should (ert--proper-list-p '(1 2 3 4)))
|
|
(should (not (ert--proper-list-p 'a)))
|
|
(should (not (ert--proper-list-p '(1 . a))))
|
|
(should (not (ert--proper-list-p '(1 2 . a))))
|
|
(should (not (ert--proper-list-p '(1 2 3 . a))))
|
|
(should (not (ert--proper-list-p '(1 2 3 4 . a))))
|
|
(let ((a (list 1)))
|
|
(setf (cdr (last a)) a)
|
|
(should (not (ert--proper-list-p a))))
|
|
(let ((a (list 1 2)))
|
|
(setf (cdr (last a)) a)
|
|
(should (not (ert--proper-list-p a))))
|
|
(let ((a (list 1 2 3)))
|
|
(setf (cdr (last a)) a)
|
|
(should (not (ert--proper-list-p a))))
|
|
(let ((a (list 1 2 3 4)))
|
|
(setf (cdr (last a)) a)
|
|
(should (not (ert--proper-list-p a))))
|
|
(let ((a (list 1 2)))
|
|
(setf (cdr (last a)) (cdr a))
|
|
(should (not (ert--proper-list-p a))))
|
|
(let ((a (list 1 2 3)))
|
|
(setf (cdr (last a)) (cdr a))
|
|
(should (not (ert--proper-list-p a))))
|
|
(let ((a (list 1 2 3 4)))
|
|
(setf (cdr (last a)) (cdr a))
|
|
(should (not (ert--proper-list-p a))))
|
|
(let ((a (list 1 2 3)))
|
|
(setf (cdr (last a)) (cddr a))
|
|
(should (not (ert--proper-list-p a))))
|
|
(let ((a (list 1 2 3 4)))
|
|
(setf (cdr (last a)) (cddr a))
|
|
(should (not (ert--proper-list-p a))))
|
|
(let ((a (list 1 2 3 4)))
|
|
(setf (cdr (last a)) (cdddr a))
|
|
(should (not (ert--proper-list-p a)))))
|
|
|
|
(ert-deftest ert-test-parse-keys-and-body ()
|
|
(should (equal (ert--parse-keys-and-body '(foo)) '(nil (foo))))
|
|
(should (equal (ert--parse-keys-and-body '(:bar foo)) '((:bar foo) nil)))
|
|
(should (equal (ert--parse-keys-and-body '(:bar foo a (b)))
|
|
'((:bar foo) (a (b)))))
|
|
(should (equal (ert--parse-keys-and-body '(:bar foo :a (b)))
|
|
'((:bar foo :a (b)) nil)))
|
|
(should (equal (ert--parse-keys-and-body '(bar foo :a (b)))
|
|
'(nil (bar foo :a (b)))))
|
|
(should-error (ert--parse-keys-and-body '(:bar foo :a))))
|
|
|
|
|
|
(ert-deftest ert-test-run-tests-interactively ()
|
|
:tags '(:causes-redisplay)
|
|
(let ((passing-test (make-ert-test :name 'passing-test
|
|
:body (lambda () (ert-pass))))
|
|
(failing-test (make-ert-test :name 'failing-test
|
|
:body (lambda () (ert-fail
|
|
"failure message")))))
|
|
(let ((ert-debug-on-error nil))
|
|
(let* ((buffer-name (generate-new-buffer-name " *ert-test-run-tests*"))
|
|
(messages nil)
|
|
(mock-message-fn
|
|
(lambda (format-string &rest args)
|
|
(push (apply #'format format-string args) messages))))
|
|
(save-window-excursion
|
|
(unwind-protect
|
|
(let ((case-fold-search nil))
|
|
(ert-run-tests-interactively
|
|
`(member ,passing-test ,failing-test) buffer-name
|
|
mock-message-fn)
|
|
(should (equal messages `(,(concat
|
|
"Ran 2 tests, 1 results were "
|
|
"as expected, 1 unexpected"))))
|
|
(with-current-buffer buffer-name
|
|
(goto-char (point-min))
|
|
(should (equal
|
|
(buffer-substring (point-min)
|
|
(save-excursion
|
|
(forward-line 4)
|
|
(point)))
|
|
(concat
|
|
"Selector: (member <passing-test> <failing-test>)\n"
|
|
"Passed: 1\n"
|
|
"Failed: 1 (1 unexpected)\n"
|
|
"Total: 2/2\n")))))
|
|
(when (get-buffer buffer-name)
|
|
(kill-buffer buffer-name))))))))
|
|
|
|
(ert-deftest ert-test-special-operator-p ()
|
|
(should (ert--special-operator-p 'if))
|
|
(should-not (ert--special-operator-p 'car))
|
|
(should-not (ert--special-operator-p 'ert--special-operator-p))
|
|
(let ((b (ert--gensym)))
|
|
(should-not (ert--special-operator-p b))
|
|
(fset b 'if)
|
|
(should (ert--special-operator-p b))))
|
|
|
|
(ert-deftest ert-test-list-of-should-forms ()
|
|
(let ((test (make-ert-test :body (lambda ()
|
|
(should t)
|
|
(should (null '()))
|
|
(should nil)
|
|
(should t)))))
|
|
(let ((result (let ((ert-debug-on-error nil))
|
|
(ert-run-test test))))
|
|
(should (equal (ert-test-result-should-forms result)
|
|
'(((should t) :form t :value t)
|
|
((should (null '())) :form (null nil) :value t)
|
|
((should nil) :form nil :value nil)))))))
|
|
|
|
(ert-deftest ert-test-list-of-should-forms-observers-should-not-stack ()
|
|
(let ((test (make-ert-test
|
|
:body (lambda ()
|
|
(let ((test2 (make-ert-test
|
|
:body (lambda ()
|
|
(should t)))))
|
|
(let ((result (ert-run-test test2)))
|
|
(should (ert-test-passed-p result))))))))
|
|
(let ((result (let ((ert-debug-on-error nil))
|
|
(ert-run-test test))))
|
|
(should (ert-test-passed-p result))
|
|
(should (eql (length (ert-test-result-should-forms result))
|
|
1)))))
|
|
|
|
(ert-deftest ert-test-list-of-should-forms-no-deep-copy ()
|
|
(let ((test (make-ert-test :body (lambda ()
|
|
(let ((obj (list 'a)))
|
|
(should (equal obj '(a)))
|
|
(setf (car obj) 'b)
|
|
(should (equal obj '(b))))))))
|
|
(let ((result (let ((ert-debug-on-error nil))
|
|
(ert-run-test test))))
|
|
(should (ert-test-passed-p result))
|
|
(should (equal (ert-test-result-should-forms result)
|
|
'(((should (equal obj '(a))) :form (equal (b) (a)) :value t
|
|
:explanation nil)
|
|
((should (equal obj '(b))) :form (equal (b) (b)) :value t
|
|
:explanation nil)
|
|
))))))
|
|
|
|
(ert-deftest ert-test-remprop ()
|
|
(let ((x (ert--gensym)))
|
|
(should (equal (symbol-plist x) '()))
|
|
;; Remove nonexistent property on empty plist.
|
|
(ert--remprop x 'b)
|
|
(should (equal (symbol-plist x) '()))
|
|
(put x 'a 1)
|
|
(should (equal (symbol-plist x) '(a 1)))
|
|
;; Remove nonexistent property on nonempty plist.
|
|
(ert--remprop x 'b)
|
|
(should (equal (symbol-plist x) '(a 1)))
|
|
(put x 'b 2)
|
|
(put x 'c 3)
|
|
(put x 'd 4)
|
|
(should (equal (symbol-plist x) '(a 1 b 2 c 3 d 4)))
|
|
;; Remove property that is neither first nor last.
|
|
(ert--remprop x 'c)
|
|
(should (equal (symbol-plist x) '(a 1 b 2 d 4)))
|
|
;; Remove last property from a plist of length >1.
|
|
(ert--remprop x 'd)
|
|
(should (equal (symbol-plist x) '(a 1 b 2)))
|
|
;; Remove first property from a plist of length >1.
|
|
(ert--remprop x 'a)
|
|
(should (equal (symbol-plist x) '(b 2)))
|
|
;; Remove property when there is only one.
|
|
(ert--remprop x 'b)
|
|
(should (equal (symbol-plist x) '()))))
|
|
|
|
(ert-deftest ert-test-remove-if-not ()
|
|
(let ((list (list 'a 'b 'c 'd))
|
|
(i 0))
|
|
(let ((result (ert--remove-if-not (lambda (x)
|
|
(should (eql x (nth i list)))
|
|
(incf i)
|
|
(member i '(2 3)))
|
|
list)))
|
|
(should (equal i 4))
|
|
(should (equal result '(b c)))
|
|
(should (equal list '(a b c d)))))
|
|
(should (equal '()
|
|
(ert--remove-if-not (lambda (x) (should nil)) '()))))
|
|
|
|
(ert-deftest ert-test-remove* ()
|
|
(let ((list (list 'a 'b 'c 'd))
|
|
(key-index 0)
|
|
(test-index 0))
|
|
(let ((result
|
|
(ert--remove* 'foo list
|
|
:key (lambda (x)
|
|
(should (eql x (nth key-index list)))
|
|
(prog1
|
|
(list key-index x)
|
|
(incf key-index)))
|
|
:test
|
|
(lambda (a b)
|
|
(should (eql a 'foo))
|
|
(should (equal b (list test-index
|
|
(nth test-index list))))
|
|
(incf test-index)
|
|
(member test-index '(2 3))))))
|
|
(should (equal key-index 4))
|
|
(should (equal test-index 4))
|
|
(should (equal result '(a d)))
|
|
(should (equal list '(a b c d)))))
|
|
(let ((x (cons nil nil))
|
|
(y (cons nil nil)))
|
|
(should (equal (ert--remove* x (list x y))
|
|
;; or (list x), since we use `equal' -- the
|
|
;; important thing is that only one element got
|
|
;; removed, this proves that the default test is
|
|
;; `eql', not `equal'
|
|
(list y)))))
|
|
|
|
|
|
(ert-deftest ert-test-set-functions ()
|
|
(let ((c1 (cons nil nil))
|
|
(c2 (cons nil nil))
|
|
(sym (make-symbol "a")))
|
|
(let ((e '())
|
|
(a (list 'a 'b sym nil "" "x" c1 c2))
|
|
(b (list c1 'y 'b sym 'x)))
|
|
(should (equal (ert--set-difference e e) e))
|
|
(should (equal (ert--set-difference a e) a))
|
|
(should (equal (ert--set-difference e a) e))
|
|
(should (equal (ert--set-difference a a) e))
|
|
(should (equal (ert--set-difference b e) b))
|
|
(should (equal (ert--set-difference e b) e))
|
|
(should (equal (ert--set-difference b b) e))
|
|
(should (equal (ert--set-difference a b) (list 'a nil "" "x" c2)))
|
|
(should (equal (ert--set-difference b a) (list 'y 'x)))
|
|
|
|
;; We aren't testing whether this is really using `eq' rather than `eql'.
|
|
(should (equal (ert--set-difference-eq e e) e))
|
|
(should (equal (ert--set-difference-eq a e) a))
|
|
(should (equal (ert--set-difference-eq e a) e))
|
|
(should (equal (ert--set-difference-eq a a) e))
|
|
(should (equal (ert--set-difference-eq b e) b))
|
|
(should (equal (ert--set-difference-eq e b) e))
|
|
(should (equal (ert--set-difference-eq b b) e))
|
|
(should (equal (ert--set-difference-eq a b) (list 'a nil "" "x" c2)))
|
|
(should (equal (ert--set-difference-eq b a) (list 'y 'x)))
|
|
|
|
(should (equal (ert--union e e) e))
|
|
(should (equal (ert--union a e) a))
|
|
(should (equal (ert--union e a) a))
|
|
(should (equal (ert--union a a) a))
|
|
(should (equal (ert--union b e) b))
|
|
(should (equal (ert--union e b) b))
|
|
(should (equal (ert--union b b) b))
|
|
(should (equal (ert--union a b) (list 'a 'b sym nil "" "x" c1 c2 'y 'x)))
|
|
(should (equal (ert--union b a) (list c1 'y 'b sym 'x 'a nil "" "x" c2)))
|
|
|
|
(should (equal (ert--intersection e e) e))
|
|
(should (equal (ert--intersection a e) e))
|
|
(should (equal (ert--intersection e a) e))
|
|
(should (equal (ert--intersection a a) a))
|
|
(should (equal (ert--intersection b e) e))
|
|
(should (equal (ert--intersection e b) e))
|
|
(should (equal (ert--intersection b b) b))
|
|
(should (equal (ert--intersection a b) (list 'b sym c1)))
|
|
(should (equal (ert--intersection b a) (list c1 'b sym))))))
|
|
|
|
(ert-deftest ert-test-gensym ()
|
|
;; Since the expansion of `should' calls `ert--gensym' and thus has a
|
|
;; side-effect on `ert--gensym-counter', we have to make sure all
|
|
;; macros in our test body are expanded before we rebind
|
|
;; `ert--gensym-counter' and run the body. Otherwise, the test would
|
|
;; fail if run interpreted.
|
|
(let ((body (byte-compile
|
|
'(lambda ()
|
|
(should (equal (symbol-name (ert--gensym)) "G0"))
|
|
(should (equal (symbol-name (ert--gensym)) "G1"))
|
|
(should (equal (symbol-name (ert--gensym)) "G2"))
|
|
(should (equal (symbol-name (ert--gensym "foo")) "foo3"))
|
|
(should (equal (symbol-name (ert--gensym "bar")) "bar4"))
|
|
(should (equal ert--gensym-counter 5))))))
|
|
(let ((ert--gensym-counter 0))
|
|
(funcall body))))
|
|
|
|
(ert-deftest ert-test-coerce-to-vector ()
|
|
(let* ((a (vector))
|
|
(b (vector 1 a 3))
|
|
(c (list))
|
|
(d (list b a)))
|
|
(should (eql (ert--coerce-to-vector a) a))
|
|
(should (eql (ert--coerce-to-vector b) b))
|
|
(should (equal (ert--coerce-to-vector c) (vector)))
|
|
(should (equal (ert--coerce-to-vector d) (vector b a)))))
|
|
|
|
(ert-deftest ert-test-string-position ()
|
|
(should (eql (ert--string-position ?x "") nil))
|
|
(should (eql (ert--string-position ?a "abc") 0))
|
|
(should (eql (ert--string-position ?b "abc") 1))
|
|
(should (eql (ert--string-position ?c "abc") 2))
|
|
(should (eql (ert--string-position ?d "abc") nil))
|
|
(should (eql (ert--string-position ?A "abc") nil)))
|
|
|
|
(ert-deftest ert-test-mismatch ()
|
|
(should (eql (ert--mismatch "" "") nil))
|
|
(should (eql (ert--mismatch "" "a") 0))
|
|
(should (eql (ert--mismatch "a" "a") nil))
|
|
(should (eql (ert--mismatch "ab" "a") 1))
|
|
(should (eql (ert--mismatch "Aa" "aA") 0))
|
|
(should (eql (ert--mismatch '(a b c) '(a b d)) 2)))
|
|
|
|
(ert-deftest ert-test-string-first-line ()
|
|
(should (equal (ert--string-first-line "") ""))
|
|
(should (equal (ert--string-first-line "abc") "abc"))
|
|
(should (equal (ert--string-first-line "abc\n") "abc"))
|
|
(should (equal (ert--string-first-line "foo\nbar") "foo"))
|
|
(should (equal (ert--string-first-line " foo\nbar\nbaz\n") " foo")))
|
|
|
|
(ert-deftest ert-test-explain-not-equal ()
|
|
(should (equal (ert--explain-not-equal nil 'foo)
|
|
'(different-atoms nil foo)))
|
|
(should (equal (ert--explain-not-equal '(a a) '(a b))
|
|
'(list-elt 1 (different-atoms a b))))
|
|
(should (equal (ert--explain-not-equal '(1 48) '(1 49))
|
|
'(list-elt 1 (different-atoms (48 "#x30" "?0")
|
|
(49 "#x31" "?1")))))
|
|
(should (equal (ert--explain-not-equal 'nil '(a))
|
|
'(different-types nil (a))))
|
|
(should (equal (ert--explain-not-equal '(a b c) '(a b c d))
|
|
'(proper-lists-of-different-length 3 4 (a b c) (a b c d)
|
|
first-mismatch-at 3)))
|
|
(let ((sym (make-symbol "a")))
|
|
(should (equal (ert--explain-not-equal 'a sym)
|
|
`(different-symbols-with-the-same-name a ,sym)))))
|
|
|
|
(ert-deftest ert-test-explain-not-equal-improper-list ()
|
|
(should (equal (ert--explain-not-equal '(a . b) '(a . c))
|
|
'(cdr (different-atoms b c)))))
|
|
|
|
(ert-deftest ert-test-significant-plist-keys ()
|
|
(should (equal (ert--significant-plist-keys '()) '()))
|
|
(should (equal (ert--significant-plist-keys '(a b c d e f c g p q r nil s t))
|
|
'(a c e p s))))
|
|
|
|
(ert-deftest ert-test-plist-difference-explanation ()
|
|
(should (equal (ert--plist-difference-explanation
|
|
'(a b c nil) '(a b))
|
|
nil))
|
|
(should (equal (ert--plist-difference-explanation
|
|
'(a b c t) '(a b))
|
|
'(different-properties-for-key c (different-atoms t nil))))
|
|
(should (equal (ert--plist-difference-explanation
|
|
'(a b c t) '(c nil a b))
|
|
'(different-properties-for-key c (different-atoms t nil))))
|
|
(should (equal (ert--plist-difference-explanation
|
|
'(a b c (foo . bar)) '(c (foo . baz) a b))
|
|
'(different-properties-for-key c
|
|
(cdr
|
|
(different-atoms bar baz))))))
|
|
|
|
(ert-deftest ert-test-abbreviate-string ()
|
|
(should (equal (ert--abbreviate-string "foo" 4 nil) "foo"))
|
|
(should (equal (ert--abbreviate-string "foo" 3 nil) "foo"))
|
|
(should (equal (ert--abbreviate-string "foo" 3 nil) "foo"))
|
|
(should (equal (ert--abbreviate-string "foo" 2 nil) "fo"))
|
|
(should (equal (ert--abbreviate-string "foo" 1 nil) "f"))
|
|
(should (equal (ert--abbreviate-string "foo" 0 nil) ""))
|
|
(should (equal (ert--abbreviate-string "bar" 4 t) "bar"))
|
|
(should (equal (ert--abbreviate-string "bar" 3 t) "bar"))
|
|
(should (equal (ert--abbreviate-string "bar" 3 t) "bar"))
|
|
(should (equal (ert--abbreviate-string "bar" 2 t) "ar"))
|
|
(should (equal (ert--abbreviate-string "bar" 1 t) "r"))
|
|
(should (equal (ert--abbreviate-string "bar" 0 t) "")))
|
|
|
|
(ert-deftest ert-test-explain-not-equal-string-properties ()
|
|
(should
|
|
(equal (ert--explain-not-equal-including-properties #("foo" 0 1 (a b))
|
|
"foo")
|
|
'(char 0 "f"
|
|
(different-properties-for-key a (different-atoms b nil))
|
|
context-before ""
|
|
context-after "oo")))
|
|
(should (equal (ert--explain-not-equal-including-properties
|
|
#("foo" 1 3 (a b))
|
|
#("goo" 0 1 (c d)))
|
|
'(array-elt 0 (different-atoms (?f "#x66" "?f")
|
|
(?g "#x67" "?g")))))
|
|
(should
|
|
(equal (ert--explain-not-equal-including-properties
|
|
#("foo" 0 1 (a b c d) 1 3 (a b))
|
|
#("foo" 0 1 (c d a b) 1 2 (a foo)))
|
|
'(char 1 "o" (different-properties-for-key a (different-atoms b foo))
|
|
context-before "f" context-after "o"))))
|
|
|
|
(ert-deftest ert-test-equal-including-properties ()
|
|
(should (equal-including-properties "foo" "foo"))
|
|
(should (ert-equal-including-properties "foo" "foo"))
|
|
|
|
(should (equal-including-properties #("foo" 0 3 (a b))
|
|
(propertize "foo" 'a 'b)))
|
|
(should (ert-equal-including-properties #("foo" 0 3 (a b))
|
|
(propertize "foo" 'a 'b)))
|
|
|
|
(should (equal-including-properties #("foo" 0 3 (a b c d))
|
|
(propertize "foo" 'a 'b 'c 'd)))
|
|
(should (ert-equal-including-properties #("foo" 0 3 (a b c d))
|
|
(propertize "foo" 'a 'b 'c 'd)))
|
|
|
|
(should-not (equal-including-properties #("foo" 0 3 (a b c e))
|
|
(propertize "foo" 'a 'b 'c 'd)))
|
|
(should-not (ert-equal-including-properties #("foo" 0 3 (a b c e))
|
|
(propertize "foo" 'a 'b 'c 'd)))
|
|
|
|
;; This is bug 6581.
|
|
(should-not (equal-including-properties #("foo" 0 3 (a (t)))
|
|
(propertize "foo" 'a (list t))))
|
|
(should (ert-equal-including-properties #("foo" 0 3 (a (t)))
|
|
(propertize "foo" 'a (list t)))))
|
|
|
|
(ert-deftest ert-test-stats-set-test-and-result ()
|
|
(let* ((test-1 (make-ert-test :name 'test-1
|
|
:body (lambda () nil)))
|
|
(test-2 (make-ert-test :name 'test-2
|
|
:body (lambda () nil)))
|
|
(test-3 (make-ert-test :name 'test-2
|
|
:body (lambda () nil)))
|
|
(stats (ert--make-stats (list test-1 test-2) 't))
|
|
(failed (make-ert-test-failed :condition nil
|
|
:backtrace nil
|
|
:infos nil)))
|
|
(should (eql 2 (ert-stats-total stats)))
|
|
(should (eql 0 (ert-stats-completed stats)))
|
|
(should (eql 0 (ert-stats-completed-expected stats)))
|
|
(should (eql 0 (ert-stats-completed-unexpected stats)))
|
|
(ert--stats-set-test-and-result stats 0 test-1 (make-ert-test-passed))
|
|
(should (eql 2 (ert-stats-total stats)))
|
|
(should (eql 1 (ert-stats-completed stats)))
|
|
(should (eql 1 (ert-stats-completed-expected stats)))
|
|
(should (eql 0 (ert-stats-completed-unexpected stats)))
|
|
(ert--stats-set-test-and-result stats 0 test-1 failed)
|
|
(should (eql 2 (ert-stats-total stats)))
|
|
(should (eql 1 (ert-stats-completed stats)))
|
|
(should (eql 0 (ert-stats-completed-expected stats)))
|
|
(should (eql 1 (ert-stats-completed-unexpected stats)))
|
|
(ert--stats-set-test-and-result stats 0 test-1 nil)
|
|
(should (eql 2 (ert-stats-total stats)))
|
|
(should (eql 0 (ert-stats-completed stats)))
|
|
(should (eql 0 (ert-stats-completed-expected stats)))
|
|
(should (eql 0 (ert-stats-completed-unexpected stats)))
|
|
(ert--stats-set-test-and-result stats 0 test-3 failed)
|
|
(should (eql 2 (ert-stats-total stats)))
|
|
(should (eql 1 (ert-stats-completed stats)))
|
|
(should (eql 0 (ert-stats-completed-expected stats)))
|
|
(should (eql 1 (ert-stats-completed-unexpected stats)))
|
|
(ert--stats-set-test-and-result stats 1 test-2 (make-ert-test-passed))
|
|
(should (eql 2 (ert-stats-total stats)))
|
|
(should (eql 2 (ert-stats-completed stats)))
|
|
(should (eql 1 (ert-stats-completed-expected stats)))
|
|
(should (eql 1 (ert-stats-completed-unexpected stats)))
|
|
(ert--stats-set-test-and-result stats 0 test-1 (make-ert-test-passed))
|
|
(should (eql 2 (ert-stats-total stats)))
|
|
(should (eql 2 (ert-stats-completed stats)))
|
|
(should (eql 2 (ert-stats-completed-expected stats)))
|
|
(should (eql 0 (ert-stats-completed-unexpected stats)))))
|
|
|
|
|
|
(provide 'ert-tests)
|
|
|
|
;;; ert-tests.el ends here
|