Vim - vimtestにモック機能を追加した(vmock連携)
先日作成したこちらのモックライブラリ。
Vim - Vim script用のモックライブラリvmockを作った
これをvimtest側でも使えるようにしました。
コード例
上記記事の例をvimtestで書きなおしてみます。
webapi-vimをモックに置き換えるという例です。
プロダクトコード
function! SampleReadFeed(url) let feeds = [] for item in webapi#feed#parseURL(a:url) " some processing... call add(feeds, item) endfor return feeds endfunction
SampleReadFeedは内部で webapi#feed#parseURL
を呼んでおり、
そのままではテスト実行時に通信が発生してしまいます。
モックを使わないテストコード(通信発生しちゃう)
let s:t = vimtest#new('Sample') function! s:make_item(title, link) return {'title': a:title, 'link': a:link} endfunction function! s:t.test() " expected data let items = [s:make_item('Title-1', 'http://localhost/hoge'), \ s:make_item('Title-2', 'http://localhost/piyo'), \ s:make_item('Title-3', 'http://localhost/fuga')] let url = 'http://rss.slashdot.org/Slashdot/slashdot' call self.assert.equals(items, SampleReadFeed(url)) endfunction
実際に通信が発生するため、このままではもちろん失敗します。
Sample [ ] test # Sample (in 19-2057.vim) 1) 'test' is FAILED Failed asserting that two values are equal - expected:[{'link': 'http://localhost/hoge', 'title': 'Title-1'}, {'link': 'http://localhost/piyo', 'title': 'Title-2'}, {'link': 'http://localhost/fuga', 'title': 'Title-3'}] + actual:[{'id': 'http://slashdot.feedsportal.com/...(長いので省略)] Test cases run: 1, Assertions: 1, Passes: 0, Failures: 1
モックを使ったテストコード(通信発生しない)
vmockの呼び出しを追加します。
let s:t = vimtest#new('Sample') function! s:make_item(title, link) return {'title': a:title, 'link': a:link} endfunction function! s:t.test() " expected data let items = [s:make_item('Title-1', 'http://localhost/hoge'), \ s:make_item('Title-2', 'http://localhost/piyo'), \ s:make_item('Title-3', 'http://localhost/fuga')] let url = 'http://rss.slashdot.org/Slashdot/slashdot' call vmock#mock('webapi#feed#parseURL').with(url).return(items).once() call self.assert.equals(items, SampleReadFeed(url)) endfunction
Sample [x] test Test cases run: 1, Assertions: 1, Passes: 1, Failures: 0
通りました。
失敗するケースも見てましょう
期待する引数と実際の引数が違った
実際の呼び出し時の引数を適当にしてみます。
call self.assert.equals(items, SampleReadFeed('invalid'))
Sample [ ] test # Sample (in 19-2057.vim) 1) 'test' is FAILED Exception:VMock:The args[0] expected: 'http://rss.slashdot.org/Slashdot/slashdot'. but received: 'invalid'. in function vimtest#run..466..vimtest#util#safety_call..vmock#verify..vmock#verify_with_event..498..vmock#exception#throw, line 1 Test cases run: 1, Assertions: 2, Passes: 1, Failures: 1
期待する呼び出し回数ではなかった
1度だけ(once)指定になっていますが、わざと2度呼んでみます。
call self.assert.equals(items, SampleReadFeed(url)) call self.assert.equals(items, SampleReadFeed(url))
Sample [ ] test # Sample (in 19-2057.vim) 1) 'test' is FAILED Exception:VMock:expected: only once. but received: 2 times. in function vimtest#run..518..vimtest#util#safety_call..vmock#verify..vmock#verify_with_event..550..vmock#exception#throw, line 1 Test cases run: 1, Assertions: 3, Passes: 2, Failures: 1
vmock単体で使う場合と記述上で異なるのは、vmock#verify
と vmock#clear
を呼ばなくて済むことです。
おわり
モックの細かい使い方は上記記事かvmockのヘルプを参照してください。