Vim scriptのテストを行うvimtestプラグインを書いた
Vim scriptのテスティングフレームワークはいくつかあります。
以前調べたこともあります。
UTを使ってVim scriptのテストを書く - ぼっち勉強会
既存プラグインでも充分に機能を備えているのですが、以下の点で不満がありました。
- Vimから気軽に実行できない
- 出力結果が物足りない
- 更新されてなかったりする
ということで、せっかくだから勉強がてら自分で作ってみました。
kannokanno/vimtest · GitHub
使い方
※追記
以下に書かれている使い方は、一部古い情報があります。
最新の情報についてはREADMEもしくはヘルプ、もしくはsample.vimを参考にしてください。
※追記ここまで
sample/sample.vimにサンプルがありますが、簡単にご紹介します。
最初にテストケースのインスタンスを作成します。
引数にはテストケース名を渡すことができ、未指定の場合は"Test"となります。
let testcase = vimtest#new() let testcase = vimtest#new('さんぷる')
あとはこのtestcaseにテストを追加していきます。
ここで日本語が使えないのが痛いなーと感じています。
function! testcase.hogehoge_test() let x = 1 let y = 2 call self.assert.equals(3, x + y) endfunction
最後に、実行するためにvimtest#run()を書いてください。
全体ではこのようになります。
let testcase = vimtest#new('さんぷる') function! testcase.hogehoge_test() let x = 1 let y = 2 call self.assert.equals(3, x + y) endfunction call vimtest#run()
あとはこのファイルをsourceすればOKです。
実行用のコマンドは特にありません。
ぼくはquickrunを使っているので、これがあればいいやと思って今のところなしです。
例えば下記のようなautocmdを定義しておけば保存時に勝手にテストしてくれて便利です。
autocmd BufWritePost,FileWritePost *_test.vim QuickRun
実行すると次のように出力されます。
. Test cases run: 1, Passes: 1, Failures: 0
失敗メッセージ
以下のような失敗だらけのテストケースがあるとして
let testcase = vimtest#new('failed test1') function! testcase.failed() call self.assert.equals(2, 1) endfunction function! testcase.error() hogeee endfunction let testcase = vimtest#new('failed test2') function! testcase.failed() call self.assert.equals(2, []) endfunction call vimtest#run()
これを実行した際の出力はこうなります。
EFE # failed test1 1) failed Failed asserting expected:<2> but was:<1> 2) error Excpetion:Vim:E492: エディタのコマンドではありません: hogeee in function vimtest#run..1283..1286, 行 1 # failed test2 1) failed Excpetion:Vim(if):E691: リスト型はリスト型としか比較できません in function vimtest#run..1298..1300..1287, 行 9 FAILURES! Test cases run: 3, Passes: 0, Failures: 3
ちょっと微妙なのが、エラーの発生箇所がvimtest#run内部になってしまいます。
これをちゃんと呼び出し元の情報を表示したいんですが、やり方が分かりませんでした。
setupとか
あります。
以下の名前で定義してもらえれば動きます。
- startup テストケース開始前に一度だけ呼ばれる
- setup テストメソッド開始前に都度呼ばれる
- teardown テストメソッド終了後に都度呼ばれる
- shutdown テストケース終了後に一度だけ呼ばれる
let testcase = vimtest#new('prepare flow') function! testcase.startup() echo 'startup' endfunction function! testcase.setup() echo ' setup' endfunction function! testcase.test_one() echo ' test one' endfunction function! testcase.test_two() echo ' test two' endfunction function! testcase.test_three() echo ' test three' endfunction function! testcase.teardown() echo ' teardown' endfunction function! testcase.shutdown() echo 'shutdown' echo '' endfunction call vimtest#run()
startup setup test three teardown setup test two teardown setup test one teardown shutdown Test cases run: 0, Passes: 0, Failures: 0
ユーザー定義変数or関数
self.customに追加できます。
定義した値はもちろんテストメソッドの中から参照できます。
vimtest#newによって返されるインスタンスは異なるので、testcase単位で共通的な情報を持つことができます。
let testcase = vimtest#new('custom') function! testcase.setup() " self.customはdictなので、変数を持たせたい場合は辞書で再代入する let self.custom = {'expected': 0} " dictなのでfunctionを追加することも可能 function! self.custom.dataProvider() return [2, 4, 6] endfunction endfunction function! testcase.test_one() for d in self.custom.dataProvider() call self.assert.equals(self.custom.expected, d % 2) endfor endfunction function! testcase.test_two() for d in self.custom.dataProvider() call self.assert.false(d % 2) endfor endfunction let testcase = vimtest#new('another custom') function! testcase.test_another() " 別オブジェクトなので未定義のためエラー for d in self.custom.dataProvider() call self.assert.false(d % 2) endfor endfunction call vimtest#run()
......E # another custom 1) test_another Excpetion:Vim(for):E716: 辞書型にキーが存在しません: dataProvider() in function vimtest#run..1576..1578, 行 2 FAILURES! Test cases run: 7, Passes: 6, Failures: 1
assert
まだ少ないです。執筆時点では以下の4つしかありません。
- self.assert.equals(expected, actual)
- expected ==# actual ならOK
- self.assert.notEquals(x, y)
- x ==# y じゃなければOK
- self.assert.true(actual)
- actualが1ならOK
- self.assert.false(actual)
- actualが0ならOK
既存プラグインと比べると機能的に物足りない部分は色々あります。
バッファのテストとかできませんし。複数のテストファイルをまとめて実行も今はできません。
ただ個人的な好みである「Vimから気軽に実行したい」は一応出来たかなと。
あとは実際に自分で使いながら拡張していこうかなと思っています。