summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Whitton <spwhitton@spwhitton.name>2016-10-08 22:02:38 -0300
committerSean Whitton <spwhitton@spwhitton.name>2016-10-08 22:02:38 -0300
commit8ba875597eadde65e8578509af3ebbebe2e3ef86 (patch)
tree25f4e0fed7c4c478c7a46b488b8fca167c172880
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--Cask3
-rw-r--r--README.md71
-rw-r--r--ert-async.el92
3 files changed, 166 insertions, 0 deletions
diff --git a/Cask b/Cask
new file mode 100644
index 0000000..491ead7
--- /dev/null
+++ b/Cask
@@ -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