Vim script のユニットテスト用のコード書いている

今年中に書いておきたかったネタその1。


前々から真面目に書こうと思っていたんですが、最近やっととりかかりました。
この手のテストモジュールは殆ど触ったことがないのでどういう風な構造やエラーメッセージを出力すればいいのかよくわかってないので結構手探りで書いている。
ひとまず難しいことはあまり考えずに『書きやすさ重視』で考えている。
現状はこんな感じ。

[ソース]

function! s:plus(a, b)
    return type(a:a) == type("") && type(a:b) == type("") 
\        ? a:a . a:b
\        : a:a + a:b
endfunction


" テストコードを記述するスクリプトローカル関数を定義する
" s:test_{名前} 名で定義
function! s:test_plus_success()
    " 引数の式が真であれば成功
    " スクリプトローカル関数を渡すことが出来る
    OwlCheck s:plus(1, 2) == 3

    " ローカル変数を参照することも可能
    let homumami = "homumami"
    OwlCheck s:plus("homu", "mami") == homumami
    
    " OwlEqual s:plus(1, 2) ==  s:plus(5, -2) とほぼ等価
    OwlEqual s:plus(1, 2), s:plus(5, -2)
    
    " 例外排出時のチェック
    OwlThrow s:plus([], {}), E745
endfunction

function! s:test_plus_failure()
    OwlCheck s:plus(1, 2) == 1

    let mamihomu = "mamihomu"
    OwlCheck s:plus("homu", "mami") == mamihomu

    " OwlCheck とは違い
    " s:plus(1, 2) と s:plus(5, -5) が評価された値が出力される
    OwlEqual s:plus(1, 2), s:plus(5, -5)
    
    OwlThrow s:plus([], {}), E740
endfunction


" テストコードが書かれたファイル名を渡す
" 自動的に s:test_{名前} の関数を評価する
call owl#run(expand("<sfile>"))

" 直接関数を呼び出しても可
" call s:test_plus_success()
" call s:test_plus_failure()

" quickrun.vim で実行する場合
" QuickRun -outputter quickfix

[出力]

in function <SNR>275_test_plus_failure
D:/test/main.vim:31:[failure] s:plus(1, 2) == 1
D:/test/main.vim:35:[failure] s:plus("homu", "mami") == mamihomu
D:/test/main.vim:38:[failure] 3 == 0
D:/test/main.vim:41:[failure] s:plus([], {}), E740

[動作イメージ]


テストの書き方はテスト関数を定義してその中にテストコードを書いていく感じ。
テストの実行は owl#run 関数にテストファイルを渡したりテストが書かれている関数を直接呼び出したり実行します。
出力は errorformat に対応させてあるので quickrun.vim で実行させればそのまま quickfix に出力させる事も出来ます。
上記の場合だと quickfix に出力させて hier.vim でハイライトしています。


テストの定義方法は基本的にコマンドに式を渡して書きます。
コマンドだとコマンド内でローカル変数が使えるのが利点なんですよね。
スクリプトローカル関数はそのままだと使えないけど…。
とりあえず、基本的な機能はだいたい揃って来ているのであとはオプションとか細かい設定出来るようにするぐらいかな。
あとは自分のプラグインで使ってみて調整していく感じかなぁ。


ちなみに実際に使用してみたい場合は下記のプラグインが必要になります。

NeoBundle "osyo-manga/vim-owl"
NeoBundle "osyo-manga/vim-budou"
NeoBundle "osyo-manga/vim-chained"