0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

1文字のずれも許さないVimおじさんに怒られないために vi/ex 自動テストを viMarkdown に組み込んだ話

0
Last updated at Posted at 2026-11-03

※ この記事は Qiita/Zenn への同時投稿です。

はじめに

筆者はマークダウンエディタ viMarkdown を開発中だ。Qt C++ によるネイティブデスクトップアプリである。
Windows用バイナリ、ソースコードは下記で公開中だ。
https://github.com/vivisuke/viMarkdown
個人利用は無料で、社会人の業務利用にはライセンス料(2,000〜4,000円)が必要である。

ver 0.3 は、5月に開発版、8月にアルファ版、10月にベータ版と進み、12月に RC・Stable のリリースを予定している。その目玉のひとつが vi/ex コマンドサポートだ。

ただし、viMarkdown は Vim の全コマンドをサポートするものではない。対応しているのは、ノーマル・ビジュアル・挿入の3モードを中心とした基本操作で、undo も回数制限なく利用できる。ex コマンドについても、対応は一部にとどまっている。

にもかかわらず、vi コマンドの挙動が1文字でもずれていると Vim おじさんが怒ることが大きな懸案事項だ。

なぜVimおじさんは1文字のずれで怒るのか

Vim おじさんは、カーソル移動時にどのコマンドを使うか意識していない。移動先を認識するだけで、手が勝手に vi コマンドを奏でる。
なので、カーソル移動後編集コマンドを実行すると、編集結果が意図しないことになる危険性があるのだ。

そのため、カーソル移動が1文字でもずれるのには耐えられないのである。

自動テストの必要性

そこで、徹底的なテスト・調整が必要なのだが、vi コマンドは組み合わせが爆発的で、膨大な工数を要する。工数が operator × motion × count の掛け算になるからだ。

  • operator: c d y < >
  • motion: h j k l Spc BS w W e E b B 0 ^ $ f F t T , ;
  • count: 2w 3dd など

カーソル位置が1文字でもずれると即アウトだ。手動テストは無理ゲーである。局所的な対処による副作用も心配だ。

テストランナー

テストランナーはあらかじめ用意したテストケースを実行し、動作が期待通りかどうかをチェックするもので、 viMarkdown 本体に組み込んだ。専用のテストツールを別に作るのではなく、アプリ自身にテストケースを一括実行する仕組みを持たせた。

使い方は単純で、その他 > テスト > vi commands メニューからテストを実行すると、登録されたテストケースをすべて流し、結果を表示する。

テストケース

テストケースは、次の形式のデータとして定義する。

  • テスト名
  • 初期テキスト・カーソル位置
  • (vi/ex コマンド, 期待されるテキスト・カーソル位置)の繰り返し

カーソル位置は ┃、選択範囲は 《 》 で表現する。┃ が 《 》 の内側にある場合は、選択範囲の端にカーソルがあることを表す。

{ "Move cursor left", "h┃ello\n",
    {"h", "┃hello\n", "h", "┃hello\n", } },
{ "Visual mode", "h┃ello\n",
    {"v", "h《┃e》llo\n", "l", "h《e┃l》lo\n", } },
{ "Ex Delete - Current Line (:d)", "line 1\nli┃ne 2\nline 3\n",
    { ":d", "line 1\n┃line 3\n" } },

コマンドを1つ実行するたびに、その時点のテキストとカーソル位置が期待どおりかを検証する。1ケースの中でコマンドを連続して実行し、途中の状態まで含めてチェックできるのがポイントだ。

テスト結果メッセージ

正常時は、何をテストしたかとテスト件数を表示する。

テスト失敗時は、Before:(実行前)➔ Commands: ➔ Expected: ➔ Actual: を表示する。実行前の状態、実行したコマンド、期待した結果、実際の結果を並べるので、どこで・どうずれたかが一目で分かる。

成功例(出力が長いので、途中を省略している):

Test vi commands...

Move cursor left: ..
Visual mode: ..
Change word (cw) - Single character word: .

Total: 0 failed / 648 tested. (Success:100.0%)

失敗例:

Change word (cw) - Single character word: .
[FAILED #1] wrong document text.
Before:   '┃a b c\n'
Commands: 'cw'
Expected: '┃ b c\n'
Actual:   '┃ c\n'

この失敗例は、実際に検出されたバグ(SPR #1272、修正済み)である。1文字単語への cw が、次の単語の末尾まで削除してしまっていた。

テストケース作成

テストケースは、基本的に生成 AI に作成してもらう。Muse 先生(Meta のパーソナル AI エージェント)・Gemini 先生が作成したテストケースを、チャッピー先生(ChatGPT)・Claude 先生がレビュー・修正・追加する体制だ。

テスト失敗時も AI に評価させる。失敗の原因は、vi/ex 実装、テストケース、自動テストランナーのいずれにもありうるからだ。

AI が生成したテストケースにも誤りがあった。正確には集計していないが、全体の1〜2%程度である。

実装の誤りとテストケースの誤りが一致すると、問題が表面化しない。そこで Muse が、自身の VM 上で Vim 9.1 をヘッドレス実行し、テストケースの期待値が本家 Vim の挙動と一致するかをチェックする体制にした。

結果

11/04 時点の結果は次のとおりだ。

Total: 0 failed / 648 tested. (Success:100.0%)

なお、648件はコマンドの種類数ではなく、テストケース内で検証したステップの合計である。

vi/ex 品質はかなり高水準になったと自負している。

まとめ

  • vi の挙動を忠実に再現するのは想像以上に難しく、コストがかかる
  • だが自動テストがあると安心して実装できる
  • テストケース作成は手間がかかるが、生成 AI に任せられる(ただし人間・他AI・実際の Vim でのクロスチェックは必要)
  • AIによって実装のスピードは上がるが、品質を保証する仕組みまでAI任せにしてはいけない
  • 結果:Vim おじさんにも怒られにくくなったはずだ

viMarkdown のダウンロード・試用よろしく〜。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?