initialize with first MVP
This commit is contained in:
145
lua/test-samurai/runners/go.lua
Normal file
145
lua/test-samurai/runners/go.lua
Normal file
@@ -0,0 +1,145 @@
|
||||
local util = require("test-samurai.util")
|
||||
|
||||
local runner = {
|
||||
name = "go",
|
||||
}
|
||||
|
||||
local function find_block_end(lines, start_idx)
|
||||
local depth = 0
|
||||
local started = false
|
||||
for i = start_idx, #lines do
|
||||
local line = lines[i]
|
||||
for j = 1, #line do
|
||||
local ch = line:sub(j, j)
|
||||
if ch == "{" then
|
||||
depth = depth + 1
|
||||
started = true
|
||||
elseif ch == "}" then
|
||||
if started then
|
||||
depth = depth - 1
|
||||
if depth == 0 then
|
||||
return i - 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return #lines - 1
|
||||
end
|
||||
|
||||
local function find_test_functions(lines)
|
||||
local funcs = {}
|
||||
for i, line in ipairs(lines) do
|
||||
local name = line:match("^%s*func%s+([%w_]+)%s*%(")
|
||||
if not name then
|
||||
name = line:match("^%s*func%s+%([^)]-%)%s+([%w_]+)%s*%(")
|
||||
end
|
||||
if name and line:find("%*testing%.T") then
|
||||
local start_0 = i - 1
|
||||
local end_0 = find_block_end(lines, i)
|
||||
table.insert(funcs, {
|
||||
name = name,
|
||||
start = start_0,
|
||||
["end"] = end_0,
|
||||
})
|
||||
end
|
||||
end
|
||||
return funcs
|
||||
end
|
||||
|
||||
local function find_t_runs(lines, func)
|
||||
local subtests = {}
|
||||
for i = func.start + 1, func["end"] do
|
||||
local line = lines[i + 1]
|
||||
if line then
|
||||
local name = line:match("t%.Run%(%s*['\"]([^'\"]+)['\"]")
|
||||
if name then
|
||||
local start_idx = i + 1
|
||||
local end_0 = find_block_end(lines, start_idx)
|
||||
table.insert(subtests, {
|
||||
name = name,
|
||||
start = start_idx - 1,
|
||||
["end"] = end_0,
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
return subtests
|
||||
end
|
||||
|
||||
local function escape_pattern(str)
|
||||
local escaped = str:gsub("(%W)", "%%%1")
|
||||
return "^" .. escaped .. "$"
|
||||
end
|
||||
|
||||
function runner.is_test_file(bufnr)
|
||||
local path = util.get_buf_path(bufnr)
|
||||
if not path or path == "" then
|
||||
return false
|
||||
end
|
||||
return path:sub(-8) == "_test.go"
|
||||
end
|
||||
|
||||
function runner.find_nearest(bufnr, row, _col)
|
||||
if not runner.is_test_file(bufnr) then
|
||||
return nil, "not a Go test file"
|
||||
end
|
||||
|
||||
local lines = util.get_buf_lines(bufnr)
|
||||
local funcs = find_test_functions(lines)
|
||||
|
||||
local current
|
||||
for _, f in ipairs(funcs) do
|
||||
if row >= f.start and row <= f["end"] then
|
||||
current = f
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if not current then
|
||||
return nil, "cursor not inside a test function"
|
||||
end
|
||||
|
||||
local subtests = find_t_runs(lines, current)
|
||||
local inside_sub
|
||||
for _, sub in ipairs(subtests) do
|
||||
if row >= sub.start and row <= sub["end"] then
|
||||
inside_sub = sub
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
local path = util.get_buf_path(bufnr)
|
||||
local root = util.find_root(path, { "go.mod", ".git" })
|
||||
|
||||
if inside_sub then
|
||||
local full = current.name .. "/" .. inside_sub.name
|
||||
return {
|
||||
file = path,
|
||||
cwd = root,
|
||||
test_path = full,
|
||||
scope = "subtest",
|
||||
func = current.name,
|
||||
subtest = inside_sub.name,
|
||||
}
|
||||
else
|
||||
return {
|
||||
file = path,
|
||||
cwd = root,
|
||||
test_path = current.name,
|
||||
scope = "function",
|
||||
func = current.name,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
function runner.build_command(spec)
|
||||
local pattern = escape_pattern(spec.test_path)
|
||||
local cmd = { "go", "test", "./...", "-run", pattern }
|
||||
return {
|
||||
cmd = cmd,
|
||||
cwd = spec.cwd,
|
||||
}
|
||||
end
|
||||
|
||||
return runner
|
||||
Reference in New Issue
Block a user