Vim PluginでもUnit testを回したい!
こんにちは、IKです。
ところで皆さんは毎日Vim scriptを書き、Vim Pluginを公開していると思いますが、
Unit test、したくないですか...?
したいと思ったそこの貴方が今回の対象です!!!
この記事を書く際に、@kamyknさんのspelunker.vimを参考にしています。
用意するもの
以下の3点です
- Vim(必須)
- CircleCI(お好みでtravis、ジェンキンスおじさんなどでも良いでしょう)
- 重い腰を上げる勇気
(今回はCircieCIを使った方法を書きます)
テスト導入
今回は自分の作成したPluginにUnit testを導入したので、自分のPluginをベースにUnit testの導入フローを紹介したいと思います。
以下のような、Vimで天気をみるためのPluginのためのUnit testです。
ディレクトリ構造
.
├── .circleci
│ ├── .vimrc
│ └── config.yml
├── .github
│ └── ISSUE_TEMPLATE
│ ├── ISSUE_TEMPLATE.md
│ └── bug_report.md
├── .gitignore
├── LICENCE
├── README.md
├── Weather.gif
├── autoload
│ ├── Weather
│ │ ├── city
│ │ │ ├── Hiroshima.vim
│ │ │ ├── Hukuoka.vim
│ │ │ ├── Kyoto.vim
│ │ │ ├── Nagoya.vim
│ │ │ ├── Osaka.vim
│ │ │ ├── Sapporo.vim
│ │ │ ├── Sendai.vim
│ │ │ ├── Shiga.vim
│ │ │ └── Tokyo.vim
│ │ ├── returncity.vim
│ │ ├── test
│ │ │ ├── test_popup.vim
│ │ │ └── test_status.vim
│ │ └── test.vim
│ └── Weather.vim
├── doc
│ └── Weather.txt
└── plugin
└── Weather.vim
テストコードに関するスクリプトは、test
ディレクトリ内にあるtest_status.vim
とWeather
ディレクトリ内にあるtest.vim
です。
簡単にこのスクリプトについて紹介しておきます。
- test.vim
これは、testディレクトリに置かれた単体テスト用のスクリプト群をまとめて実行するためのファイルです。
- test_status.vim
これは、apiを叩いた際にhttp statusが正しく返って来ているかをtestするためのスクリプトファイルです。
testコードカキコ
じゃあ実際にtestを書いていきましょう。
test_status.vim
" test_status.vimlets:dir= expand('<sfile>:h:h').'/city'lets:city_data= map(glob(expand(s:dir).'/*.vim',1,1),'fnamemodify(v:val, ":t:r")')function! Weather#test#test_status#run()foriins:city_dataletl:id = Weather#returncity#return(i)letl:res= webapi#http#get('http://weather.livedoor.com/forecast/webservice/json/v1?city='.id)
echo i." status:".l:res.status
call assert_equal(200,l:res.status)endforendfunction
test_status.vimは、cityディレクトリにある都市のファイル名を抜き出し、その都市に対応するidを指定してapiをgetで叩き、それをassert_equal
で評価するためのスクリプトになります。
今回のケースだと、call assert_equal(200, l:res.status)
の部分がそれに当たり、これはwebapi#http#get('http://weather.livedoor.com/forecast/webservice/json/v1?city='.id)
で返ってきたhttpレスポンスが200
ならヨシ!、そうでないならダメと言う感じになります。
assert_equal
についてはこちらに記事がが参考になると思います!
test.vim
" test.vimscriptencoding utf-8lets:save_cpo=&cpo
set cpo&vimfunction! Weather#test#run()" v:errorsを初期化するletv:errors =[]call Weather#test#test_status#run()if len(v:errors)>=1
echo v:errors
" error exit
execute 'cq!'endif
echo 'test success'
execute 'qall!'endfunctionlet&cpo =s:save_cpo
unlet s:save_cpo
test.vimは、test_status.vimで実行したassert_equalの結果を返し、Vimを終了させるようなスクリプトになっています。
もし、assert_equalを実行し、問題なければ:qa!
でVimを終了、問題があれば:cq!
でVimを終了させるスクリプトになっています。
circle ciの設定
testが書けたらあとはcircle ciに丸投げしちゃいましょう!!
version:2jobs:build:docker:-image:centos:7working_directory:~/projectsteps:-checkout-run:name:lscommand:ls -la-run:name:yumcommand:yum update -y && yum install make gcc ncurses-devel ssh git -y-run:name:Build latest Vimcommand:git clone https://github.com/vim/vim.git && (cd vim && make && make install)-run:name:Vim versioncommand:vim --version-run:name:Install webapi-vimcommand:git clone https://github.com/mattn/webapi-vim-run:name:write .vimrccommand:mv ~/project/.circleci/.vimrc ~/.vimrc-run:name:check pathcommand:ls -la && pwd-run:name:Unit testcommand:vim +":call Weather#test#run()"
これで、circle ciくんが自動でVimを起動し、テストを動かし、Vimを終了するところまで自動で回してくれます!
自動化って素晴らしい!!
やっていることとしては、
- yumをupdate
- 必要なpackage群をインストール
- Vimをビルド
- pluginをインストール
- vimrcをホームディレクトリに配置(もっといい方法あると思います)
- Vimを起動し、上記のtest用の関数を呼び出す
これがtest用のvimrcです
scriptencoding utf-8set encoing=utf-8
syntax enable
set runtimepath+=~/project
set runtimepath+=~/project/webapi-vim
スクリーンショット
テストが成功した図
テストが失敗して絶望している図
最後に
どうでしたか?
これでより豊かなVim lifeが送れることでしょう!
Happy Vimming!!
次の@aiya000さんの記事にも期待です!!
参考文献
https://thinca.hatenablog.com/entry/20151203/1449076256
https://github.com/kamykn/spelunker.vim