vimtest修正記録-Vim scriptテスト用にモック機能を書いてみたpart2
vimtestについてはこちらVim scriptのテストを行うvimtestプラグインを書いた - ぼっち勉強会
モチベーション維持と振り返りのための記録
- モック機能書いてみた
モック機能書いてみた
前回の雛形をもとにアレコレ考えて修正した
ソースは長くなってしまったのでGistに置いておくとして、使い方はこんな感じ
動作環境はMacだけ。他の環境で動くかは分からない
使い方の概要
- (必須)モックオブジェクトを生成する
- 対象コードが書かれているソースファイルを指定
- (必須)モックとする関数名を指定する
- (任意)必要があれば引数の指定や戻り値の指定をする
- (必須)期待する呼び出し回数を定義する
let s:mock = s:mock(expand('%:p')) call s:mock.function('hello').with('World', 'Vim').return('hogehoge').once() echo s:hello('world', 'vim') call s:mock.assert()
- モック対象となるサンプルコード
function! s:echo() echo 100 endfunction function! s:hello(text1, text2) return 'Hello, ' . a:text1 . ' and ' . a:text2 endfunction
前提
以降のケースではすでにモックオブジェクトが生成済みとする
let s:mock = s:mock(expand('%:p'))
ケース1:引数や戻り値は特にいじらず、一度だけ呼ばれることを検証する
call s:mock.function('echo').once() call s:echo() call s:mock.assert()
複数回s:echoを呼ぶと失敗メッセージが出る
試しに3回呼んでみるとこうなる
100
100
100
Function echo called expected 1 but was 3
ケース2:実行された際の処理をフックし、一度だけ呼ばれることを検証する
" コールバック用の関数 function! s:echo_callback() echo 'callback dayo' endfunction call s:mock.function('echo').callback('echo_callback').once() call s:echo() " => callback dayo call s:mock.assert() call s:echo() " => 100
mock.assert()した後はもとの定義に戻る
ケース3:例外を発生させるようにし、一度だけ呼ばれることを検証する
call s:mock.function('echo').throw('booo').once() try call s:echo() catch /booo/ echo 'error dayo' " => error dayo endtry call s:mock.assert() call s:echo() " => 100
ケース4:引数の検証をし、一度だけ呼ばれることを検証する
call s:mock.function('hello').with('World', 'Vim').once() echo s:hello('World', 'Vim') "echo s:hello('World', 'Emacs') " => Function hello args expected ['World', 'Vim'] but was ['World', 'Emacs'] call s:mock.assert()
ケース5:戻り値をフックし、一度だけ呼ばれることを検証する
call s:mock.function('hello').return('hogehoge').once() echo s:hello('World', 'Vim') " => hogehoge call s:mock.assert() echo s:hello('World', 'Vim') " => Hello, World and Vim
ケース6:引数の検証と戻り値をフックし、一度だけ呼ばれることを検証する
call s:mock.function('hello').with('World', 'Vim').return('hogehoge').once() echo s:hello('World', 'Vim') " => hogehoge call s:mock.assert() echo s:hello('World', 'Vim') " => Hello, World and Vim
ケース7:引数の検証と戻り値をフックする。呼び出し回数は検証しない
call s:mock.function('hello').with('World', 'Vim').return('hogehoge').any() echo s:hello('World', 'Vim') " => hogehoge echo s:hello('World', 'Vim') " => hogehoge echo s:hello('World', 'Vim') " => hogehoge call s:mock.assert() echo s:hello('World', 'Vim') " => Hello, World and Vim
課題
現状のやつはvimtestに取り込むとして、このままだと辞書の関数がcall()で呼べないのでどうしようかな
サンプルコード
let s:dict = {} function! s:dict.sample() return 'hogeee' endfunction let s:out = '' redir => s:out silent! function s:dict.sample redir END echo s:out unlet s:out
関数名を表示させて、例えばそれが5360だった場合
:echo call('5360', []) " => E725: 辞書用関数が呼ばれましたが辞書がありません: 5360
うーん、:functionの結果に出力されないし、辞書関数ってcall経由で呼べないのだろうか