Neovimで現在のファイルのテストをすぐ開く

「現在開いているファイルに対応するテストファイル」をすぐ開くためのNeovimのキーマップを紹介します。

キーマップ

次のように設定します。

local function open_test_or_src_file()
-- 現在開いているファイルのパスを取得
local current_file = vim.fn.expand("%")
local dir = vim.fn.fnamemodify(current_file, ":h")
local file_name = vim.fn.fnamemodify(current_file, ":t:r")
local ext = vim.fn.fnamemodify(current_file, ":e")
local candidates = {}
if current_file:match("test") or current_file:match("spec") then
local target_file_name = file_name:gsub("%.test$", ""):gsub("%.spec$", "")
candidates = {
dir .. "/" .. target_file_name .. "." .. ext,
dir:gsub("/test$", "") .. "/" .. target_file_name .. "." .. ext,
string.gsub(dir, "^test", "src") .. "/" .. target_file_name .. "." .. ext,
}
else
candidates = {
dir .. "/" .. file_name .. ".test." .. ext,
dir .. "/" .. file_name .. ".spec." .. ext,
dir .. "/test/" .. file_name .. "." .. ext,
string.gsub(dir, "^src", "test") .. "/" .. file_name .. "." .. ext,
}
end
-- ファイルが存在するか確認して開く
for _, test_file in ipairs(candidates) do
if vim.fn.filereadable(test_file) == 1 then
vim.cmd("edit " .. test_file)
return
end
end
-- ファイルが見つからなかった場合
print("There is no test file.")
end
vim.keymap.set("n", "<Space>gt", open_test_or_src_file, { desc = "Open test file" })

テストファイルを開いている時に「テストされる側のファイル」を開くこともできます。

テストファイルの対応例

しくみとしては、テストファイルがありそうな場所を探し、ファイルが存在すれば開くだけです。
たとえばsrc/a/b/c.tsに対しては次の場所にテストファイルがないか確認します。

  • src/a/b/c.test.ts
  • src/a/b/c.spec.ts
  • src/a/b/test/c.ts
  • test/a/b/c.ts

あくまでもファイルのパスから判定しているだけです。そのため、「実際に関数をimportしてテストしているか」や「拡張子が違う場合」などは考えていません。あまり厳密な実装では無いですが、とりあえず自分が使う分にはこれで良さそうです。

おまけ(Angular向け)

上記の実装を流用してAngular向けのキーマップも設定しようかと思いましたが、別の形で実現することにしました。備忘録として残しておきます。

やろうとしたこと

Angularでは次のように拡張子だけ違うファイルを行き来することがよくあります。

  • foo/foo.component.ts
  • foo/foo.component.html
  • foo/foo.component.scss
  • foo/foo.component.spec.ts

このように対応するファイルの一覧を表示し、選択して開こうと思いました。

実際のキーマップ

telescope.nvimfind_filesを使えば似たようなことはできるため、今のところ次のように設定しています。

vim.keymap.set("n", "<Leader>gc", function()
require("telescope.builtin").find_files({ cwd = require("telescope.utils").buffer_dir() })
end)

現在のファイルのディレクトリ以下にあるファイルの一覧を開くキーマップです。


以上、テストファイルやAngularで使えるキーマップの紹介でした。