5.3 KiB
5.3 KiB
ERT Quick Reference
Test Definition
(ert-deftest NAME ()
[DOCSTRING]
[:tags (TAG...)]
BODY...)
Example:
(ert-deftest my-pkg-test-feature ()
"Test feature implementation."
:tags '(unit quick)
(should (my-pkg-feature-works)))
Assertions
| Macro | Purpose | Example |
|---|---|---|
(should FORM) |
Assert true | (should (= 4 (+ 2 2))) |
(should-not FORM) |
Assert false | (should-not (zerop 5)) |
(should-error FORM [:type TYPE]) |
Assert error | (should-error (/ 1 0) :type 'arith-error) |
Running Tests
Interactive
M-x ert RET SELECTOR RET
Common selectors:
t- All tests"^my-pkg-"- Tests matching regex:tag quick- Tests with tag:failed- Failed tests from last run(not :tag slow)- Exclude slow tests
Batch Mode
# Run all tests
emacs -batch -l ert -l tests.el -f ert-run-tests-batch-and-exit
# Run specific tests
emacs -batch -l ert -l tests.el \
--eval '(ert-run-tests-batch-and-exit "^test-feature-")'
# Quiet mode
emacs -batch -l ert -l tests.el \
--eval '(let ((ert-quiet t)) (ert-run-tests-batch-and-exit))'
Interactive Debugging Keys
In *ert* results buffer:
| Key | Command | Description |
|---|---|---|
. |
Jump to definition | Open test source code |
d |
Debug test | Re-run with debugger |
b |
Show backtrace | Display failure backtrace |
r |
Re-run test | Re-run test at point |
R |
Re-run all | Re-run all tests |
l |
Show assertions | Display executed should forms |
m |
Show messages | Display test messages |
TAB |
Expand/collapse | Toggle test details |
Test Environment Patterns
Temporary Buffer
(with-temp-buffer
(insert "content")
(my-function)
(should (string= (buffer-string) "expected")))
Cleanup
(let ((resource (create-resource)))
(unwind-protect
(should (use-resource resource))
(cleanup-resource resource)))
Local Variables
(let ((my-var 'test-value))
(should (eq 'test-value (get-my-var))))
Mocking
With cl-letf
(cl-letf (((symbol-function 'external-fn)
(lambda () "mocked")))
(should (string= "mocked" (calls-external-fn))))
With flet (older style)
(require 'cl)
(flet ((external-fn () "mocked"))
(should (string= "mocked" (calls-external-fn))))
Skip Tests
;; Skip if condition false
(skip-unless (featurep 'some-feature))
;; Skip if condition true
(skip-when (eq system-type 'windows-nt))
Test Organization
Naming Convention
;; Format: package-test-feature
(ert-deftest my-package-test-parsing () ...)
(ert-deftest my-package-test-validation () ...)
Tags
(ert-deftest test-quick ()
:tags '(quick unit)
...)
(ert-deftest test-slow ()
:tags '(slow integration)
...)
;; Run: M-x ert RET :tag quick RET
;; Run: M-x ert RET (not :tag slow) RET
Fixture Pattern
(defun with-test-fixture (body)
"Execute BODY within test fixture."
(let ((setup (do-setup)))
(unwind-protect
(funcall body setup)
(do-teardown setup))))
(ert-deftest my-test ()
(with-test-fixture
(lambda (fixture)
(should (test-with fixture)))))
Common Test Patterns
Testing Errors
;; Any error
(should-error (/ 1 0))
;; Specific error type
(should-error (error "msg") :type 'error)
(should-error (/ 1 0) :type 'arith-error)
Testing Buffer State
(with-temp-buffer
(my-mode)
(should (eq major-mode 'my-mode))
(should (local-variable-p 'my-mode-var)))
Testing Interactive Commands
(with-temp-buffer
(insert "text")
(goto-char (point-min))
(call-interactively 'my-command)
(should (= (point) 5)))
Testing Messages
(let ((messages))
(cl-letf (((symbol-function 'message)
(lambda (fmt &rest args)
(push (apply #'format fmt args) messages))))
(my-function)
(should (member "Expected message" messages))))
Test File Template
;;; my-package-test.el --- Tests for my-package -*- lexical-binding: t -*-
;;; Commentary:
;; Test suite for my-package.
;;; Code:
(require 'ert)
(require 'my-package)
(ert-deftest my-package-test-basic ()
"Test basic functionality."
(should (my-package-function)))
(provide 'my-package-test)
;;; my-package-test.el ends here
Makefile Integration
.PHONY: test
test:
emacs -batch -l ert \
-l my-package.el \
-l test/my-package-test.el \
-f ert-run-tests-batch-and-exit
CI/CD (GitHub Actions)
- name: Run tests
run: |
emacs -batch -l ert \
-l my-package.el \
-l test/my-package-test.el \
-f ert-run-tests-batch-and-exit
Key Best Practices
- Name descriptively:
package-test-featureformat - Use tags: Organize by speed/type
- Isolate environment:
let, temp buffers - Always cleanup:
unwind-protect - Mock I/O: Avoid filesystem/network
- Test errors: Use
should-error - One focus per test: Clear failures
- Add docstrings: Document test purpose
Resources
- Manual:
C-h i m ert RET - Online: https://www.gnu.org/software/emacs/manual/html_mono/ert.html
- Source:
lisp/emacs-lisp/ert.el