Help us understand the problem. What is going on with this article?

NeoBundle + Vesting 使ってVim plugin テストを自動化

More than 5 years have passed since last update.

はじめに

最近, Vim pluginを開発するようになって, テストをCIでぶん回したくなったので, 試行錯誤の結果メモ.

やりたいこと

僕はあんまりテストに深い思い入れがある訳ではないのだけど, 下記を実現したい気持ちがあった.

  1. コーディング中はVimから単体テストを実行したい.
  2. CIでもテストを回したいため, CLIからの実行も欲しい. READMEに"build passing"のバッジ貼りたい.
  3. テストを実行するための依存プラグイン管理の仕組みが欲しい.

Vim plguinのCIについて適当にググってみたところ, vim-flavorでテストをCLIから実行する, という方法が見つかったのだが, これは上記の1. と3. と背反するため, 今回は採用見送り.
また, vim-flavorは依存プラグインのバージョン指定がsemverに従ってないと上手く動作しない様子だったため, これも採用見送りの理由の一つ.

結局, 上記を全部充足するようなVimプラグインは特に見つからなかったので, NeoBundle + vesting + シェルスクリプトの構成を採用することにした.
NeoBundleは普段から使っているplugin manager, という理由.
vestingについては, 特に深い思いがある訳ではないが, NeoBundleと作者が一緒であり, 上記の1.に対応していたため.

やってみた

基本的な考え方

先述の通り, Vimを立ち上げてからの実行はvestingで出来るので, 作り込む必要があるのはCLI部分のみ.
今回は以下のアプローチでやってみた.

  1. レポジトリにneobundle.vimをclone.
  2. テスト用の.vimrcを用意し, テストに必要なVimの設定情報は事前に記述しておく.
    • プラグイン本体, NeoBundleのruntimepath設定はこのファイルに記述
    • テスト実行時に必要となる依存pluginはこのファイル中に:NeoBundle コマンドで列挙し, :NeoBundleInstall で取得する
  3. vestingを実行するためのマクロを用意する.
    • vestingはUniteで結果を出力するため, この結果をログに吐き出すようにしておく.
  4. Vimをsilent-modeで起動する. vim -u vest/.vimrc -s vest/_runner.
  5. vestの結果ログに[Fail], [Error]が存在するかどうか, grepする. 該当無しであればテスト成功とみなす.

コード解説

さて, 実際にQuramy/vesting-ciにサンプルのレポジトリ作って, TravisCIで動かしてみた.

レポジトリのディレクトリ構成は下記のようにしている.

ディレクトリ構成
- vesting-ci           # レポジトリのルート. 
 - autoload/
  |  calc.vim          # テスト対象コード
 + bundle/             # NeoBundleでinstallするpluginディレクトリ
 + neobundle.vim/      # NeoBundle本体
 - vest/               # vestingのテストコード用ディレクトリ
  |  .vimrc            # 2.の設定ファイル
  |  _runner           # 3.のvesting実行マクロ
  |  calc_add.vim      # vestingのテストコードその1
  |  calc_sub.vim      # vestingのテストコードその2
 + vim/
   runtest.sh          # CLI用シェルスクリプト
   .travis.yml         # TraviceCI設定ファイル

vestingはカレントディレクトリ配下のvest/*.vimをテストコードとみなして実行するため, テスト関係のファイルは極力ここに突っ込むようにした.

テスト対象のコードは下記. と言っても只の足し算と引き算.

autoload/calc.vim
function! calc#add(a, b)
  return a:a + a:b
endfunction

function! calc#sub(a, b)
  return a:a - a:b
endfunction

対応するvestingのテストコードは下記.

vest/calc_add.vim
scriptencoding utf-8

Context Vesting.run()
  It calc#add returns the summation of two values
    Should calc#add(1, 2) == 3
  End
End
Fin

vest/calc_sub.vimも似たような感じ. ちなみに, vestingは:Unite vesting:. をVimから実行すると, テストの一覧がUnite上に表示されるので, 実行したいテストファイルを選択してEnterを叩くとテストが実行される.

ここからがこのエントリの主眼. まずは上記2. の.vimrc から.

vest/.vimrc
if has('vim_starting')
  set nocompatible
  let s:basedir = expand('<sfile>:p:h').'/../'

  " プラグイン自体をruntimepathに登録.
  execute('set runtimepath+='.s:basedir)

  " NeoBundleをruntimepathに登録.
  execute('set runtimepath+='.s:basedir.'neobundle.vim')

  " NeoBundleで依存pluginを記載.
  " Uniteとvestingは必須.
  call neobundle#begin(expand(s:basedir.'bundle'))
  NeoBundle 'Shougo/unite.vim'
  NeoBundle 'Shougo/vesting'
  call neobundle#end()

  " 必要なpluginの一括install
  silent NeoBundleInstall
endif

Uniteとvestingは最低限必要となるpluginである. もし, 他に必要なpluginがあれば, NeoBundleを追記していけばよい.
(僕が実際に開発しているPluginでは, vimprocを使ってるいるが, このファイルに追記している)

続いて3.のvesting実行マクロ.

vest/_runner
:Unite vesting:.
*
:call unite#action#do('start')
:w vest/test_result.log
:quitall
vim:ft=vim

vestingを実行した後, *で全テストファイルを選択. uniteのstart actionを実行すると, 全テストが実行されて結果がUniteのバッファに表示されるので, これをファイルに保存するようにしている.
あんまりスマートじゃない気もするが, 取り合えず動いてるのでこれでよし.
なお, このファイルの拡張子に.vimを付けてないのは, vestingがテストコードだと誤解しないようにするため.

最後にCLI用のシェルスクリプトとTravisCIの設定ファイル.
実際はディレクトリの存在チェックとか, Vim自体のビルド処理(TravisCIのVimが7.3で古いので)も書いているため, もう少し長くなるのだけど, 先述した方法の骨子を抜きだすとこんな感じだ.

runtest.sh
#/bin/sh

VIMRC_FILE="vest/.vimrc"
DRIVER_FILE="vest/_runner"
RESULT_FILE="vest/test_result.log"

# 1. NeoBundleのクローン
git clone https://github.com/Shougo/neobundle.vim

# 4. Vestingの実行
vim -u ${VIMRC_FILE} -s ${DRIVER_FILE}
cat ${RESULT_FILE}

# 5. テスト結果の判定
grep -E "\[Fail\]" ${RESULT_FILE} > /dev/null
if [ $? -eq 0 ]; then
  exit 1
fi
grep -E "\[Error\]" ${RESULT_FILE} > /dev/null
if [ $? -eq 0 ]; then
  exit 1
fi
.travis.yml
script:
- sh runtest.sh

所感

最初はVim plguinのCI化は結構敷居が高そうに思っていたが, やってみると意外と簡単.

テスティングフレームワークに依存するのはマクロ部分だけなので, vesting以外のフレームワーク使ってる場合でも, 考え方とかシェルは使いまわせる予感.

参考

Quramy
Front-end web developer. TypeScript, Angular and Vim, weapon of choice.
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした