I like the Python feature of doc-tests for testing functions independently. Does Emacs Lisp have something similar, or could I emulate it in some way?
For example, this function gets timestamps from an Org-mode clock segment:
(defun org-get-timestamps (line)
"Parses a clock segment line and returns the first and last timestamps in a list."
(let* ((org-clock-regexp (concat "CLOCK: " org-ts-regexp3 "--" org-ts-regexp3))
(t1 (if (string-match org-clock-regexp line)
(match-string 1 line)
(user-error "The argument must have a valid CLOCK range")))
(t2 (match-string 9 line)))
(cons t1 (cons t2 '()))))
I would like a doc-test such as:
(org-get-timestamps "CLOCK: [2019-09-26 Thu 00:29]--[2019-09-26 Thu 01:11] => 0:42") ("2019-09-26 Thu 00:29" "2019-09-26 Thu 01:11")
A test of the user-error
would also be nice.
I also would like to ensure that any refactoring passes the doc-test, so it's also a regression test.
Does that exist?
An important feature of Python doctest is how its input looks like a Python interactive REPL session, as described in the doctest documentation:
The doctest module searches for pieces of text that look like interactive Python sessions, and then executes those sessions to verify that they work exactly as shown.
I'm not aware of any elisp facilities exactly like this, but I think you can achieve what you want using the Emacs Lisp Regression Testing (ERT) framework, which supports both interactive and batch test execution.
To test the org-get-timestamps
function you can define a test like this:
(require 'ert)
(ert-deftest org-timestamp-test ()
(should (equal
(org-get-timestamps "CLOCK: [2019-09-26 Thu 00:29]--[2019-09-26 Thu 01:11] => 0:42")
'("2019-09-26 Thu 00:29" "2019-09-26 Thu 01:11"))))
To run the test interactively, you can type M-x ert, press enter, and then either press enter again to select all tests using the default t
argument or type the name of the test to run and press enter, and the test results will be shown in the *ert*
buffer:
Selector: org-timestamp-test
Passed: 1
Failed: 0
Skipped: 0
Total: 1/1
Started at: 2019-09-27 08:44:57-0400
Finished.
Finished at: 2019-09-27 08:44:57-0400
.
The dot character at the very end above represents the test that was run. If multiple tests were executed, there would be multiple dots.
To run the test in batch mode, save it to file org-timestamp-test.el
and assuming the org-get-timestamps
function resides in file org-timestamps.el
, run it like this from your shell command line:
emacs -batch -l ert -l org-timestamps.el -l org-timestamp-test.el -f ert-run-tests-batch-and-exit
The test results are then presented on the shell output:
Running 1 tests (2019-09-27 06:03:09-0700) passed 1/1 org-timestamp-test
Ran 1 tests, 1 results as expected (2019-09-27 06:03:09-0700)