vim9scriptで書いた.vimrcのテストをvim9scriptで書いてGithub Actionsでpush時に実行するようにした話
初めに
vim9scriptで書いた.vimrcのテストをvim9scriptで書いてGithub ActionsでPush時にテストするようにしてみました
もともとvim標準のassertを使って「vim9scriptで書いた.vimrcのテストをvim9scriptで書いて」はやっていたのですが
某読書会で「自動でテストしないの?」「vim-themis良いよー」と教えていただいたのでやってみました
この場をかりて読書会の皆様に感謝を🙏
テストを書く
というわけでテストをvim-themisで書き直します
themis#helper('expect')
は関数への参照なので先頭大文字の変数に代入しないといけないのがポイントです
だいたいこんな感じです
(全部書くと長いので全てを読みたい奇特な方は記事最後記載のリポジトリを参照ください)
vim9script
var suite = themis#suite('Test for .vimrc')
const assert = themis#helper('assert')
const Expect = themis#helper('expect')
source expand('~/.vimrc')
suite.Foo = () => {
assert.equals('foo', 'foo')
Expect('bar').to_be('bar')
}
結果は省略
themisの出力、見やすくてよいですね
.vimrc内のスクリプトローカルな関数をテストしたい
SIDをscriptnames
で取得できるのでそれを利用します
(vital.vimにもあったような?)
# スクリプトローカルな関数をテストするためにSIDを確保しておく
var scriptnames_output = ''
redir => scriptnames_output
silent scriptnames
redir END
const vimrc_sid = scriptnames_output
->split("\n")
->filter((i, v) => v =~# '/\.vimrc$')[0]
->matchstr('\d\+')
suite.Bar = () => {
const F = function($'<SNR>{vimrc_sid}_BUZ')
assert.equals(F('buz'), 'hello sid!')
}
Github Actionに登録する
こちらを参考に作成します
ただしデフォルトでインストールされるvimは古いのでvim9scriptが動きません
sudo add-apt-repository ppa:jonathonf/vim
で取得先を変更するようにしました(参考)
出来上がったSimple Workflowの設定がこちら
# This is a basic workflow to help you get started with Actions
name: CI
# Controls when the workflow will run
on:
# Triggers the workflow on push or pull request events but only for the "master" branch
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# タイムアウト(デフォルトだと6時間なので長すぎる…)
timeout-minutes: 15
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# .vimrcをチェックアウトする
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v3
# vimとgitとプラグインをインストールする
- name: Initialize
run: |
sudo apt-get update
sudo add-apt-repository ppa:jonathonf/vim
sudo apt-get install -y vim git
ln -s $GITHUB_WORKSPACE/.vimrc ~/.vimrc
# vim-jetpackでインストールしたプラグインが入った状態でテストしたいので
# JetpackSyncを実行しておく → ここに罠が!(後述)
vim -c JetpackSync -c qa!
# テストを実行する
- name: Run tests
run: |
cd $GITHUB_WORKSPACE/test
# themisのインストール先は環境に合わせてください
~/.vim/pack/jetpack/opt/vim-themis/bin/themis vimrc.test.vim
これでいいと思ってましたが…
軽く書いたテストが通ったので、ヨシ!と思ってたのですが
プラグインが有効になっていませんでした。 (themisのvim起動オプションに-u NONE
ってありますし)
また、テストコード内でsource .vimrc
をしているので.vimrcにかかれたVimEnterイベントが動きません
.vimrc内のVimEnterをテストしやすいように関数に修正することはできますがプラグインの方は手をつけられません
そもそも今回の目的はthemisとはちょっと合わなかったようです(認識間違っていたらすみません💦)
なのでテストコードに簡単なテストフレームワークを書きました
ここまできたらvim標準のassertを使ってもいいかと思いましたがせっかくなのでthemisと同じ形で実装しました
テストに失敗したらcq
で抜ける形にすればGithub Actionsにエラーを伝えられるようです
ついでにテストコードを開いて:so %
で実行できるようにしておきました
# Github Actionsで以下の通り実行する
# cd $GITHUB_WORKSPACE/test
# vim -c vimrc.test.vim
# `:source %`で実行した場合は終了させない
var is_manually_run = expand('%:t') ==# 'vimrc.test.vim'
var suite = {}
var assert = {}
var is_faild = false
def! g:RunTests()
is_faild = false
for s in suite->keys()
echom s
suite[s]()
endfor
echom is_faild ? 'Tests faild.' : 'Tests success.'
if !is_manually_run
execute is_faild ? 'cq!' : 'q!'
endif
enddef
assert.equals = (act: any, exp: any, msg: string = 'assert.equals') => {
if act !=# exp
is_faild = true
echom $' {msg}'
echom $' act: {act}'
echom $' exp: {exp}'
endif
}
assert.falsy = (act: any, msg: string = 'assert.falsy') => {
assert.equals(act, false, msg)
}
suite.Foo = () => {
assert.equals('foo', 'foo')
Expect('bar').to_be('bar')
}
call g:RunTests()
Simple Workflowの設定も最後だけ直しておきます
- name: Run tests
run: |
cd $GITHUB_WORKSPACE/test
vim -S vimrc.test.vim
テストが通ったのでヨシ!
終わりに
後半はともかく、前半はvim9script + vim-themis + Github Actionsの参考になれば嬉しいです
全ソースはこちらにあります
Discussion