I wrote a minor mode with the purpose of modifying written text on the fly.

It is currently creating a post-self-insert-command-hook, and triggers only on specific keypresses (e.g. the space bar, a semicolon, an open parens).

As an example, the user would type select and when they press the space key, the buffer would now contain SELECT.

I'm having a hard time writing a test for this with ert. I've tried writing it thus:

(ert-deftest upcase-select ()
    (insert "select")
    (execute-kbd-macro (kbd "SPC"))
    (should (equal (buffer-string) "SELECT "))))

This test should verify that when I press the space key, the word "select" becomes the word SELECT But the test ends up comparing " " and "SELECT ".

How can I write a test that triggers the behavior I desire?

(and further: is this a terrible idea? what's a better idea?)

  • 2
    Not an answer, but it sounds like you're reimplementing abbrevs
    – Malabarba
    Dec 27, 2014 at 21:45
  • I just took another look at this. It looks like execute-kbd-macro take pre- and post-command hooks into account. In other words, your code should work. Are you sure the underlying mode sqlup-mode work as intended? Nov 1, 2015 at 8:00

4 Answers 4


I've been using ecukes to write these sorts of tests and it's brilliant.

Test cases look like this:

  # Check *args works ok
  Scenario: Space *args on its own
    When I type "f(*args)"
    Then I should see "f(*args)"

  Scenario: Space *args with other args
    When I type "f(a,*args)"
    Then I should see "f(a, *args)"

  # And **kwargs
  Scenario: Space **kwargs on its own
    When I type "f(**kwargs)"
    Then I should see "f(**kwargs)"

  Scenario: Space **kwargs with other args
    When I type "f(a,**kwargs)"
    Then I should see "f(a, **kwargs)"

I can add more details on setting it up if needed, or you can look at the project I linked (the Cask file and the features directory are relevant to ecukes).


You can see how I solved a similar problem with lispy-test.el. Here's an example test:

(ert-deftest lispy-braces ()
  (should (string= (lispy-with "\"a regex \\\\|\"" "{")
                   "\"a regex \\\\{|\\\\}\""))
  (should (string= (lispy-with "\"a string |" "{")
                   "\"a string {|}")))

lispy-with is a macro that creates a temporary file with emacs-lisp-mode, inserts the first string, calls the command sequence decoded from the second string and returns the final buffer contents:

(defmacro lispy-with (in &rest body)
     (insert ,in)
     (when (search-backward "~" nil t)
       (delete-char 1)
       (set-mark (point))
       (goto-char (point-max)))
     (search-backward "|")
     (delete-char 1)
     ,@(mapcar (lambda (x) (if (stringp x) `(lispy-unalias ,x) x)) body)
     (insert "|")
     (when (region-active-p)
       (insert "~"))
  • So.. This simulates a self-insert-command ?
    – Trevoke
    Jan 3, 2015 at 20:33
  • No, it resolves the command from the mode-map and calls it. Simulating stuff is kind of fragile. It's best to just call the command, bypassing all the interactive stuff.
    – abo-abo
    Jan 3, 2015 at 20:54
  • And what's "lispy-unalias" ?
    – Trevoke
    Jan 3, 2015 at 21:58
  • Just some function that looks up a key binding. See github.com/abo-abo/lispy/blob/master/lispy-test.el#L93
    – abo-abo
    Jan 3, 2015 at 22:51

My take on this is that execute-kbd-macro acts on the buffer of the selected window (it is effectively typed keystrokes from the user, after all), and you must therefore ensure that this is set to your temporary buffer.


  (insert "select")
    (set-window-buffer nil (current-buffer))
    (execute-kbd-macro (kbd "SPC")))

I note that the same kind of thing is going on in the code of Lindydancer's answer.


First, the idea is great, you should write this kind of test cases for your packages.

One way to do this is to insert a suitable content into a temporary buffer, add suitable keys to the input queue, break into recursive edit, and let nature have its course. This way, things like post-command hooks are executed.

For example:

(defun test-upcase-interactively ()
  (let ((unread-command-events
          (kbd "M-u")
          ;; Remove the following line to stay in recursive edit.
          (kbd "C-M-c")          ; Exit recursive edit.
        (insert "words"))
        (select-window (display-buffer (current-buffer)))
      (buffer-substring (point-min) (point-max)))))

(ert-deftest my-test ()
  (should (equal (test-upcase-interactively)

Of course, it's overkill to use the recursive edit trick for something like upcase-word, as it doesn't rely on pre- and post-commands.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.