Vim script で Assert
っぽいことを使いやすく定義してみました。
まぁ Assert といっても処理が中断するわけではないのですが。
[使い方]
function! s:plus(a, b) return a:a + a:b endfunction function! g:minus(a, b) return a:a - a:b endfunction function! s:test() let n = 10 let m = 7 " 基本的な使い方 call g:assert(1) " => OK : call g:assert(0) " => Assert : " 偽の時のメッセージを指定 call g:assert_msg(s:plus(1, 3) == 5, "g:plus(1, 3) == 5") " => Assert : g:plus(1, 3) == 5 " 文字列で式を渡せば、そのまま式がメッセージとして出力される call g:assert_expr("g:minus(1, 3) == 2") " => Assert : g:minus(1, 3) == 2 " スクリプトローカル関数も可 call g:assert_expr("s:plus(1, 3) == 2") " => Assert : s:plus(1, 3) == 2 " ローカル変数を使用する場合は、l: を渡す call g:assert_expr("s:plus(1, 3) == n", l:) " => Assert : s:plus(1, 3) == n " コマンド版 " 式がそのまま評価される Assert g:plus(1, 3) == 4 " => OK : g:plus(1, 3) == 4 Assert s:minus(1, 3) == 5 " => Assert : s:minus(1, 3) == 5 " ローカル変数も OK Assert g:plus(3, m) == n " => OK : g:plus(3, m) == n " Equal 版 " スペースで引数を区切っているので、余計なスペースが挿入できない… AssertEqual s:plus(2,m) n-5 " => Assert : s:plus(2,m) == n-5 endfunction call s:test()
式を文字列と渡して、それを評価してチェックを行います。
スクリプトローカルやローカル変数もそのまま使用できます。
:Assert コマンドを使用する場合は余計な記述を書く必要がないのでだいぶすっきりしていますね。
結構書きやすくていいんじゃないかなーと。
もうちょっと出力メッセージとかを賢くして簡単なテストモジュールとか書いてみたいところではある。
しかし、Vim script の闇が怖い…。
[注意]
スクリプト変数や関数外ではスクリプト関数は参照できませんゆえ…。
" グロバール関数は OK Assert g:plus(1, 3) == 4 " スクリプト関数は NG Assert s:minus(1, 3) == -4 let s:value = 10 function! s:test() " s:value は参照できない Assert s:value == 10 endfunction call s:test()
[ソース]
function! s:SCaller() try throw 'abc' catch /^abc$/ return matchstr(v:throwpoint, '^function \zs.\{-}\ze\.\.') endtry endfunction function! s:SID() return (split(s:SCaller(), "_") + [""])[0] endfunction let g:assert_fail_message_prefix = "Assert : " let g:assert_success_message_prefix = "OK : " function! g:assert_msg(expr, msg) if !a:expr echo g:assert_fail_message_prefix . a:msg return 0 else echo g:assert_success_message_prefix . a:msg return 1 endif endfunction function! g:assert(expr) return g:assert_msg(a:expr, "") endfunction function! g:assert_expr(expr, ...) call extend(l:, get(a:, "1", {})) try return g:assert_msg(eval(substitute(a:expr, "s:", s:SID()."_", "g")), a:expr) catch /.*/ echo "except : ". a:expr echo v:exception return 0 endtry endfunction command! -nargs=* \ Assert call g:assert_msg(eval(substitute(<q-args>, "s:", s:SID()."_", "g")), <q-args>) command! -nargs=* \ AssertEqual execute "Assert " .join([<f-args>], " == ")