ertを使ってelispのunittestを書く方法のメモ

ertを使ってelispのunittestを書く方法のメモ。ertは標準で添付されているのでインストールは不要(なはず)。

使いかた

以下のような関数を定義しておく(テスト対象)

(defun my:add (x y) (+ x y))

テストを書く。

(require 'ert)

(ert-deftest add20 ()
  (should (= 20 (my:add 10 10)))
  )

テストを実行する

  1. (M-x eval-buffer)
  2. M-x ert

ertのdefaultのtは全てのテストを実行するという意味。勝手にテストを読み込んでくれないので書いたテストを読み込んであげる必要がある(eval-buffer)。

実行結果は以下のようなもの

Selector: t
Passed:  1
Failed:  0
Skipped: 0
Total:   1/1

Started at:   2019-01-07 05:16:12+0900
Finished.
Finished at:  2019-01-07 05:16:12+0900

.

失敗した場合

以下のようなテストを追加してみる。これは絶対失敗するもの。

(ert-deftest add21 ()
  (should (= 20 (my:add 10 10)))
  )

再度ertを実行(M-x ert)

Selector: t
Passed:  1
Failed:  1 (1 unexpected)
Skipped: 0
Total:   2/2

Started at:   2019-01-07 05:14:03+0900
Finished.
Finished at:  2019-01-07 05:14:03+0900

.F

F add21
    (ert-test-failed
     ((should
       (= 21
          (my:add 10 10)))
      :form
      (= 21 20)
      :value nil))

テストの書き方

基本的にはert-deftestのマクロの中で以下を利用してassertionを書く。

  • should
  • should-not
  • should-error
  • should-not-err

あと、環境によってスキップしたいものなどは以下を使ってスキップできる。

  • skip-unless

例えば、executable-findでpylosが存在しない場合にスキップしたい場合だとか。

  (skip-unless (executable-find "pyls"))

batchで実行(CIなどに)

てきとうにmakefileを書いた。同階層のディレクトリの*test.elがテストとして認識される。何か依存しているライブラリがあった場合には-l subrを参考に追加する。

EMACS ?= emacs
SELECTOR ?= t

TESTS ?= $(wildcard *test.el)

test:
  $(EMACS) -Q --batch  -L . \
      -l subr \
      $(addprefix -l ,$(TESTS)) \
      --eval '(setq ert-batch-backtrace-right-margin 100)' \
      --eval '(ert-run-tests-batch-and-exit (quote $(SELECTOR)))'

試せるgist

けっこう出力がうるさいのが不便と言えば不便?

$ emacs -Q --batch  -L . \
    -l subr \
    -l 00test.el \
    --eval '(setq ert-batch-backtrace-right-margin 100)' \
    --eval '(ert-run-tests-batch-and-exit (quote t))'
Running 2 tests (2019-01-07 05:22:33+0900)
   passed  1/2  add20
Test add21 backtrace:
  signal(ert-test-failed (((should (= 21 (my:add 10 10))) :form (= 21 20) :value nil)))
  ert-fail(((should (= 21 (my:add 10 10))) :form (= 21 20) :value nil))
  (if (unwind-protect (setq value-7 (apply fn-5 args-6)) (setq form-description-9 (nconc (list '(sho
  (let (form-description-9) (if (unwind-protect (setq value-7 (apply fn-5 args-6)) (setq form-descri
  (let ((value-7 'ert-form-evaluation-aborted-8)) (let (form-description-9) (if (unwind-protect (set
  (let* ((fn-5 (function =)) (args-6 (condition-case err (let ((signal-hook-function (function ert--
  (lambda nil (let* ((fn-5 (function =)) (args-6 (condition-case err (let ((signal-hook-function (fu
  ert--run-test-internal(#s(ert--test-execution-info :test #s(ert-test :name add21 :documentation ni
  ert-run-test(#s(ert-test :name add21 :documentation nil :body (lambda nil (let* ((fn-5 (function =
  ert-run-or-rerun-test(#s(ert--stats :selector t :tests [#s(ert-test :name add20 :documentation nil
  ert-run-tests(t #f(compiled-function (event-type &rest event-args) #<bytecode 0x4883c9>) nil)
  ert-run-tests-batch(t)
  ert-run-tests-batch-and-exit(t)
  eval((ert-run-tests-batch-and-exit 't))
  command-line-1(("-L" "." "-l" "subr" "-l" "00test.el" "--eval" "(setq ert-batch-backtrace-right-ma
  command-line()
  normal-top-level()
Test add21 condition:
    (ert-test-failed
     ((should
       (= 21
      (my:add 10 10)))
      :form
      (= 21 20)
      :value nil))
   FAILED  2/2  add21

Ran 2 tests, 1 results as expected, 1 unexpected (2019-01-07 05:22:33+0900)

1 unexpected results:
   FAILED  add21

emacsのフォントの大きさを調節する方法のメモ

はじめに

遠くの画面に写して作業をしたくなった。デフォルトで用意されているコマンドだけでは特定のバッファのフォントの大きさを調整する方法だけしか見つからなかった。しょうがないのでちょっとしたコマンドを作った。

そのついでにemacsのフォントの大きさを調節する方法のメモ

フォントの大きさを調節する方法

相対的にフォントの大きさを変更

以下で現在のバッファ上のフォントフォントの大きさを調整(scale)できる。

  • C-x + text-scale-increase
  • C-x - text-scale-decrease

絶対的にフォントの大きさを変更(heightで指定)

(buffer local variablesのface-remapping-alistに値がどんどん追記されていくので気になる人はきれいにしたくなるかもしれない)

(setq font-height 140)
(face-remap-add-relative 'default :height font-height)

ちなみに現在のフォントの大きさ(font height)は以下で調べられる。

(* (or (nth 2 text-scale-mode-remapping) 1) (face-attribute 'default :height))

全てのバッファのフォントの大きさを変更

(set-face-attribute 'default nil :height font-height)

フォントのサイズを調節するためのコマンド

幾つかの候補を事前に設定しておき、カレントバッファでサイズを確認してから全体のバッファに適用という手順を踏めるようにした。

;; フォントのサイズの候補
(setq my:font-height-candidates '(140 220))

(lexical-let ((i 0))
  (defun* my:font-height (&optional incp &key candidates)
    (when incp
      (setq i (+ i (if (numberp incp) incp 1))))

    (let* ((candidates (or candidates my:font-height-candidates))
           (height (nth i candidates)))
      (cond ((numberp height) height)
            (t
             (setq i 0)
             (nth i candidates))))))

(defun my:adjust-font-height (arg)
  (interactive "p")
  (let* ((incp (+ 1 (/ arg 4)))
         (font-height (my:font-height incp)))
    (message "remap my font height %d (inc %d)" font-height incp)
    (face-remap-add-relative 'default :height font-height)
    ))

(defun my:adjust-font-height-globally ()
  (interactive)
  (let* ((incp nil)
         (font-height (my:font-height incp)))
    (message "remap my font height %d globally (inc %s)" font-height incp)

    ;; clear all temporary remapping setting
    (dolist (b (buffer-list))
      (with-current-buffer b
        (when face-remapping-alist
          (setq-local face-remapping-alist nil)
          )
        ))

    (set-face-attribute 'default nil :height font-height)
    ))

C-x \\C-x |に割り当ててみた。

位置のリセット機能付きのcycle-list的なものを手軽に定義できたりしないかな。