diff options
author | Sean Whitton <spwhitton@spwhitton.name> | 2016-10-08 22:02:38 -0300 |
---|---|---|
committer | Sean Whitton <spwhitton@spwhitton.name> | 2016-10-08 22:02:38 -0300 |
commit | 8ba875597eadde65e8578509af3ebbebe2e3ef86 (patch) | |
tree | 25f4e0fed7c4c478c7a46b488b8fca167c172880 |
Import ert-async-el_0.1.2.orig.tar.xz
[dgit import orig ert-async-el_0.1.2.orig.tar.xz]
-rw-r--r-- | Cask | 3 | ||||
-rw-r--r-- | README.md | 71 | ||||
-rw-r--r-- | ert-async.el | 92 |
3 files changed, 166 insertions, 0 deletions
@@ -0,0 +1,3 @@ +(source melpa) + +(package-file "ert-async.el") diff --git a/README.md b/README.md new file mode 100644 index 0000000..e7b0d90 --- /dev/null +++ b/README.md @@ -0,0 +1,71 @@ +# ert-async.el + +This library provides the function `ert-deftest-async`, which works +just like `ert-deftest`, except that it works for async tests. + +## Installation + +Add `ert-async` to your [Cask](https://github.com/cask/cask) file: + +```lisp +(depends-on "ert-async") +``` + +Add this to get font locking for `ert-deftest-async`: + +```lisp +(remove-hook 'emacs-lisp-mode-hook 'ert--activate-font-lock-keywords) +(add-hook 'emacs-lisp-mode-hook 'ert-async-activate-font-lock-keywords) +``` + +## Usage + +The function `ert-deftest-async` works just like `ert-deftest`, except +that the `callbacks` argument is a list of callback functions. Unless +all functions has been called before `ert-async-timeout` seconds, the +test fails. + +An example. When the function `async-call` callbacks, the functions +`done-1` and `done-2` are called. + +```lisp +(ert-deftest-async my-async-test (done-1 done-2) + (async-call-1 done-1) + (async-call-2 done-2)) +``` + +Note that if a callback function is called with a string as argument, +the test will fail with that error string. So if the function +`async-call` above callbacks with an argument, the test would have to +be written as: + +```lisp +(ert-deftest-async my-async-test (done-1 done-2) + (async-call-1 (lambda () (funcall done-1))) + (async-call-2 (lambda () (funcall done-2)))) +``` + +Passing a string as argument to a callback function can be useful when +you don't want a function to callback, for example: + +```lisp +(ert-deftest-async my-async-test (done) + (async-call + (lambda () + (funcall done "should not callback, but did"))) + (funcall done)) +``` + +## Contribution + +Contribution is much welcome! + +Install [Cask](https://github.com/cask/cask) if you haven't +already, then: + + $ cd /path/to/ert-async.el + $ cask + +Run all tests with: + + $ make diff --git a/ert-async.el b/ert-async.el new file mode 100644 index 0000000..4c94d7a --- /dev/null +++ b/ert-async.el @@ -0,0 +1,92 @@ +;;; ert-async.el --- Async support for ERT -*- lexical-binding: t; -*- + +;; Copyright (C) 2014 Johan Andersson + +;; Author: Johan Andersson <johan.rejeep@gmail.com> +;; Maintainer: Johan Andersson <johan.rejeep@gmail.com> +;; Version: 0.1.2 +;; Keywords: test +;; URL: http://github.com/rejeep/ert-async.el + +;; This file is NOT part of GNU Emacs. + +;;; License: + +;; 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, Inc., 51 Franklin Street, Fifth Floor, +;; Boston, MA 02110-1301, USA. + +;;; Commentary: + +;;; Code: + +(require 'ert) + +(defvar ert-async-timeout 10 + "Number of seconds to wait for callbacks before failing.") + +(defun ert-async-activate-font-lock-keywords () + "Activate font-lock keywords for `ert-deftest-async'." + (font-lock-add-keywords + nil + '(("(\\(\\<ert-deftest\\(?:-async\\)?\\)\\>\\s *\\(\\(?:\\sw\\|\\s_\\)+\\)?" + (1 font-lock-keyword-face nil t) + (2 font-lock-function-name-face nil t))))) + +(defmacro ert-deftest-async (name callbacks &rest body) + "Like `ert-deftest' but with support for async. + +NAME is the name of the test, which is the first argument to +`ert-deftest'. + +CALLBACKS is a list of callback functions that all must be called +before `ert-async-timeout'. If all callback functions have not +been called before the timeout, the test fails. + +The callback functions should be called without any argument. If +a callback function is called with a string as argument, the test +will fail with that error string. + +BODY is the actual test." + (declare (indent 2)) + (let ((varlist + (cons + 'callbacked + (mapcar + (lambda (callback) + (list + callback + `(lambda (&optional error-message) + (if error-message + (ert-fail (format "Callback %s invoked with argument: %s" ',callback error-message)) + (if (member ',callback callbacked) + (ert-fail (format "Callback %s called multiple times" ',callback)) + (push ',callback callbacked)))))) + callbacks)))) + `(ert-deftest ,name () + (let* ,varlist + (with-timeout + (ert-async-timeout + (ert-fail (format "Timeout of %ds exceeded. Expected the functions [%s] to be called, but was [%s]." + ert-async-timeout + ,(mapconcat 'symbol-name callbacks " ") + (mapconcat 'symbol-name callbacked " ")))) + ,@body + (while (not (equal (sort (mapcar 'symbol-name callbacked) 'string<) + (sort (mapcar 'symbol-name ',callbacks) 'string<))) + (accept-process-output nil 0.05))))))) + +(provide 'ert-async) + +;;; ert-async.el ends here |