EmacsLispExpectations

Last edit

Summary: Link to Lisp:ert-expectations.el

Changed:

< Lisp:el-expectations.el

to

> [new]
> The new generation of EmacsLispExpectations is available, Lisp:ert-expectations.el , using ErtTestLibrary.

> Lisp:el-expectations.el is obsolete.


Emacs Lisp Expectations is the simplest unit testing framework by rubikitch. It is very easy to use/read.

The new generation of EmacsLispExpectations is available, Lisp:ert-expectations.el , using ErtTestLibrary. Lisp:el-expectations.el is obsolete.

Mocking is done utilizing EmacsLispMock. You should download it, too:

Lisp:el-mock.el

Emacs Lisp Expectations is modeled after Ruby's expectations by Jay Fields. It inherits testing policy, designed to encourage unit testing best practices such as:

  • Discourage setting more than one expectation at a time
  • Promote maintainability by not providing a setup or teardown method
  • Provide one syntax for setting up state based or behavior based expectation
  • Focus on readability by providing no mechanism for describing an expectation other than the code in the expectation.

Usage

  1. Evaluate an expectations S-exp.
  2. ‘M-x expectations-execute’ to execute a test.
  3. If there are any errors, use ‘M-x next-error’ (C-x `) and ‘M-x previous-error’ to go to the expectations S-exp.

‘expectations’ defines a expectations test case. Use ‘expect’ and ‘desc’ to verify the code. Note that these are neither functions nor macros. These are keywords in expectations Domain Specific Language (DSL).

Synopsis

Assert that the evaluation result of BODY is ‘equal’ to EXPECTED-VALUE.

Description of a test. It is treated only as a delimiter comment.

Synopsis of EXPECTED-VALUE

Body should eq buffer object of BUFFER-NAME.

Body should match REGEXP.

Body should be a TYPE-SYMBOL. TYPE-SYMBOL must be one of symbols returned by ‘type-of’ function:

   `symbol', `integer', `float', `string', `cons', `vector',
   `char-table', `bool-vector', `subr', `compiled-function',
   `marker', `overlay', `window', `buffer', `frame', `process',
   `window-configuration'

Body should raise any error.

Body should raise ERROR-SYMBOL error.

Body should raise ERROR-SYMBOL error with ERROR-DATA. ERROR-DATA is 2nd argument of ‘signal’ function. Example:

    (expect (error wrong-number-of-arguments '(= 3))
      (= 1 2 3 ))

Body should raise any error with ERROR-MESSAGE. Example:

    (expect (error-message \"ERROR!!\")
      (error \"ERROR!!\"))

Body should call MOCK-FUNCTION-SPEC and returns MOCK-RETURN-VALUE. Mock assertion depends on ‘el-mock’ library. If available, you do not have to require it: el-expectations detects it.

Synopsis of MOCK-FUNCTION-SPEC:

    (FUNCTION ARGUMENT ...)
    MOCK-FUNCTION-SPEC is almost same as normal function call.
    If you should specify `*' as ARGUMENT, any value is accepted.
    Otherwise, body should call FUNCTION with specified ARGUMENTs.

Example:

    (expect (mock (foo * 3) => nil)
      (foo 9 3))

Body should equal (eval SEXP).

Batch Mode

If you prefer batch mode, use this script (el-expectations):

  #!/bin/sh
  EMACS=emacs
  OPTIONS="-L . -L $HOME/emacs/lisp"
  OUTPUT=/tmp/.el-expectations
  $EMACS -q --no-site-file --batch $OPTIONS -l el-expectations -f batch-expectations $OUTPUT "$@"
  ret=$?
  cat $OUTPUT
  rm $OUTPUT
  exit $ret

Batch Mode Usage

  $ el-expectations el-expectations-failure-sample.el

Example code

  (expectations
    (desc "simple expectation")
    (expect 3
      (+ 1 2))
    (expect "hoge"
      (concat "ho" "ge"))
    (expect "fuga"
      (set-buffer (get-buffer-create "tmp"))
      (erase-buffer)
      (insert "fuga")
      (buffer-string))
    (desc "extended expectation")
    (expect (buffer "*scratch*")
      (with-current-buffer "*scratch*"
        (current-buffer)))
    (expect (regexp "o")
      "hoge")
    (expect (type integer)
      3)
    (desc "error expectation")
    (expect (error arith-error)
      (/ 1 0))
    (expect (error)
      (/ 1 0)))

Translation from Ruby's expectations

  (expectations
    ;; State based expectation where a value equals another value
    (expect 2
      (+ 1 1))
    ;; State based expectation where an error is expected
    ;; Simply expect error symbol of the intended exception
    (expect (error void-function '(no-function))
      (no-function))
    ;; Behavior based test using a traditional mock
    ;; TODO implement times.
    (expect (mock (dial * "2125551212") => nil)
      (dial 'phone "2125551212")
      (dial 'phone "2125551212"))
    ;; Behavior based test on a concrete mock
    (expect (mock (deal *))
      (deal 'object))
    ;; State based test utilizing a stub
    (expect 2
      (stub two => 2)
      (two))
    ;; State based test utilizing a concrete mock
    (expect 2
      (mock (bar *) => 2)
      (bar 'object))
    ;; Behavior based test utilizing a stub and a concrete mock
    (expect 1
      (mock (give-me-three 3) => 1)
      (stub three => 3)
      (give-me-three (three)))
    ;; State based test matching a Regexp
    (expect (regexp "string")
      "a string")
    ;; State based test to determine if the object is an instance of sequence
    (expect (type sequence)
      ())
    ;; State based test to determine if the object is an instance of the class
    (expect (type string)
      "a string"))

CategoryCode UnitTesting