何の因果か最近Emacs Lispを書くことになりました。
Emacsみたいなこわいエディタの話をしているのは必然的にこわいひとが多いです。
ドラクエで例えるとキラーマシンみたいな方ばっかです。
そんな中、ひのきのぼう/たびびとのふく/Lv1 でぷるぷるしながら調べたこと試したことをまとめて公開します。
新たな勇者のぼうけんの、最初の一歩を手伝えれば幸いです。
#注意
Emacs Lispは初心者、それ以外は今回はじめて触ったという体たらくで書いた記事です。
というか、主にこのページの劣化焼き直しです。
Emacs Lispのテスト、依存性管理、CI - 備忘録
この記事を読む方は先にこちらのページをひと通り読みましょう。不自由なく理解できた方は以下を読む必要はありません。
#ERTとは
ERT is an Emacs Lisp library for regression/unit testing.
EmacsWiki: Ert Test Library
Emacs24には標準で入ってます。
ELEやrejeep/ert-runner.elのような便利糖衣もあって、この記事でやってる程度のことは全部できるっぽいですが試してません。
##つかいかた
適当なelファイル(例えばhoge-test.el)にテストコードを書いて、emacsからM-x ert
で対話的に実行できます。
複数のテストを一括でやったりCIで自動実行したりするためには、emacsのバッチモードが使えます。
$ emacs -Q -batch -l hoge-test.el -f ert-run-tests-batch-and-exit
参考:Initial Options - GNU Emacs Manual (emacs自体のオプション)
Action Arguments - GNU Emacs Manual (-batchのオプション)
##かきかた
###いあいあ えると
(require 'ert)
(require 'hoge)
(eval-when-compile
(require 'cl))
のようにertとテストしたいファイルをrequireします。
マクロは単にrequireしただけだとバイトコンパイル時にうまく置換されないようなので(eval-when-compile)で囲います。
参考:12.3 マクロとバイトコンパイル
具体的なテストはert-deftest
を使って書きますが、defun
スペシャルフォームとほぼ同じ書き方です。
###おまたせしました すごいやつ
(ert-deftest hoge-test ()
"Test of `hoge'."
(should (equal EXPECTED
ACTUAL)))
should
マクロだよ。ACTUAL
部に実際の処理を、EXPECTED
部に予期される返り値を書くことで値を比較してエラーを吐いたりしてくれるすごいやつだよ。
最低限これだけ覚えておけばテストが書けますやったね。
should
に備わった 108式まである 便利機能の詳細は以下のページを参照。
How to Write Tests - Emacs Lisp Regression Testing
###お前もERTか?ERTなら俺が相手だ
(ert-run-tests-batch-and-exit)
この式を評価すれば先述したバッチ処理がemacs内から呼べます。
具体的にはロードされてるelファイルのert-deftest
で定義されたテストをぜんぶ実行します。
複数のテストに共通する初期設定などを1ファイルで行い、そのあと各テストを呼ぶようなときに使えそうです。
#Cask
##Caskとは
Emacs用の非公式パッケージマネージャです。普段使いされてる方も多いようです。
今回は依存ライブラリをすごい勢いで解決してくれます。
インストールは公式にある通り、
$ curl -fsSkL https://raw.github.com/cask/cask/master/go | python
でOK。
以下パスも通した体で行きます。
##つかいかた
$ cask
か$ cask install
で、カレントディレクトリのCaskファイルに応じて依存関係を解決してくれます。
その後 $ cask exec emacs -Q -batch -L . -l hoge-test.el -f ert-run-tests-batch-and-exit
のようにバッチ処理。
先のバッチ処理に-L .
なるオプションが加わりましたが、.(カレントディレクトリ)
をロードパスに加える指示です。
詳細はこのへん参照。
あとcaskは、環境変数$EMACS
に応じてEmacsのバージョンを変えてくれます。
あとで.travis.yml
でこの機能使うので頭の片隅に。
##かきかた
ワーキングディレクトリにCaskファイルを作って以下を記述。
(source gnu)
(source melpa)
(source marmalade)
(files "hoge.el")
(development
(depends-on "ert")
(depends-on "cl")
)
基本Emacs Lispです。
(Emacs24.3以降しか相手にしないならclもertも標準で入ってるのでわざわざ書かなくてもいい・・・?)
cask固有の指示方法の詳細はCask Domain Specific Language — Cask 0.7.2参照。
実用的にはfileをちまちま指定せず特定ディレクトリにまとめて*.el
のように指示するか、packageにするんでしょうか。
そのへんさっぱりわかりません。今後の課題(逃げ口上)。
#Travis CI
##Travis CIとは
Githubと連携した継続的インテグレーション(CI)サービスです。フリーミアム。
githubにpushするだけでweb-hookを受け取ってテストを走らせて結果を通知してくれます。
2015年1月現在、対応言語は驚きの20種類。
C C++ Clojure C# D Erlang F# Go Groovy Haskell
Java JavaScript (with Node.js) Julia Objective-C
Perl PHP Python Ruby Rust Scala Visual Basic
はい、Lispはありませんね。
でもテスト自体はERTに任せられるので、ERTをmakeから叩けば万事OKのようです。
ターミナルからいろいろしたい人のためにgemも用意されています。
gem install travis
してtravis login --auto
するだけの簡単作業で256倍便利に。
Webのアカウント登録もgithubのログイン情報使って勝手にやってくれたしこっちでも勝手にやってくれるし便利すぎて薄気味悪い。
##とらびす だーくねす
language: emacs-lisp
env:
- EMACS=emacs23
- EMACS=emacs24
- EMACS=emacs-snapshot
matrix:
allow_failures:
- env: EMACS=emacs-snapshot
before_install:
# Install Emacs
- sudo add-apt-repository -y ppa:cassou/emacs
- sudo add-apt-repository -y ppa:ubuntu-elisp
- sudo apt-get update -qq
- sudo apt-get install -qq $EMACS
# Install Cask
- curl -fsSkL --max-time 10 --retry 10 --retry-delay 10
https://raw.github.com/cask/cask/master/go | python
- export PATH="$HOME/.cask/bin:$PATH"
- cask
script:
make
今までに解説したコマンドが総動員ですね。
env:
で指定した環境変数ごとに1回ずつ一連のコマンドを実行する、ということが分かればぜんぶ読めます。
最新のemacsを拾ってくるにあたり、Travis CI側の環境がUbuntu 12.04LTSなのでppa形式でリポジトリを追加しています。
元記事様ではppa:cassou/emacs
を採用していたようですが去年1月6日に更新を停止されたためこちらに切り替え。
では次肝心のmake。
##むーんぷりずむぱわーめいくふぁいる
EMACS ?= emacs
CASK ?= cask
all:
${MAKE} clean
${MAKE} test
${MAKE} compile
${MAKE} test
${MAKE} clean
compile:
${CASK} exec ${EMACS} -Q -batch -L . -eval "(batch-byte-compile)" hoge.el
test:
${CASK} exec ${EMACS} -Q -batch -L . -l hoge-test.el -f ert-run-tests-batch-and-exit
clean:
rm -f hoge.elc
.PHONY: all compile test clean
Makefileのお約束としてインデントはTAB文字じゃないと動きません。コピペ実行あぼん注意。
元記事様ではバイトコンパイル時に1つでもwarningが出たらmake失敗にしていたようですが、こちらはwarningのまま放置する感じです。
##でびる めいく らい
makeファイルを書いたらひとまずローカルでmake
すればテストが走ります。
エラーを全部直して一安心、いざgit push
したらTravis側ではErrorとWarningが洪水だったりする。
頑張れ。
#まとめ
ここまでひと通りやったらあとはgithubにpushすればいいです。
初回push後Travis側の処理が終わったら通知が来ます。
その後はMakeがエラー吐けば通知が来ます。
治せれば通知が来ます。
治ってから次にエラーが発生するまでは静かに暮らせます。「植物の心」のような人生を送るためにもローカルでmake回しまくりましょう。
- pushするまでもなく、ローカルの段階でmakeが通らなければ
git commit
出来ないような仕組みがあると便利そうですね。 -
gitの
pre-commit hook
機能で実現できそう。
通知形式はデフォルトではgithub登録アドレスへのメールですが、Web-hookを吐くのでなんでもできそうです。