Feature: run & debug a subtest inside table driven test cases

pull/274/head
ray-x 1 year ago
parent 1f52335ea3
commit f33866ed00

@ -20,10 +20,11 @@ local namepath = {}
local function extract_filepath(msg)
msg = msg or ""
log(msg)
--[[ or [[ findAllSubStr_test.go:234: Error inserting caseResult1: operation error DynamoDB: PutItem, exceeded maximum number of attempts]]
-- or 'path/path2/filename.go:50:11: Error xxx
local pos, _ = msg:find([[[%w_-/]+%.go:%d+:]])
local pos, _ = msg:find([[[%w_-%./]+%.go:%d+:]])
if pos then
local pos2 = msg:find(":")
local s = msg:sub(1, pos2 - 1)
@ -42,6 +43,9 @@ local function extract_filepath(msg)
if namepath[s] ~= nil then
return namepath[s]
end
if vim.fn.filereadable(s) == 1 then
return
end
if vim.fn.executable("find") == 0 then
return
end
@ -55,12 +59,12 @@ local function extract_filepath(msg)
end
for _, value in pairs(path) do
local st, _ = value:find(s)
log(msg, value, st)
if st then
-- find cmd returns `./path/path2/filename.go`, the leading './' is not needed for quickfix
local p = value:sub(3, st - 1)
namepath[st] = p
return p
local path = value:sub(1, st - 1)
log(value, st, path)
namepath[st] = path
return path
end
end
end
@ -181,12 +185,17 @@ function M.make(...)
if optarg["v"] then
table.insert(cmd, "-v")
end
if not bench and compile_test then
table.insert(cmd, "-c")
end
if optarg["r"] then
log("run test", efm)
table.insert(cmd, "-run")
end
if not bench and compile_test then
table.insert(cmd, "-c")
if optarg["f"] == 'uzz' then
log("fuzz test")
table.insert(cmd, "-fuzz")
end
end
@ -276,7 +285,7 @@ function M.make(...)
if value:find("FAIL") == nil then
local p = extract_filepath(value)
if p then
value = package_path .. util.ltrim(value)
value = package_path:gsub('%.%.%.', '') .. util.ltrim(value)
end
end
else

@ -205,6 +205,9 @@ return {
require('go.gotest').test_func(unpack(opts.fargs))
end, { nargs = '*' })
create_cmd('GoTestSubCase', function(opts)
require('go.gotest').test_tblcase(unpack(opts.fargs))
end, { nargs = '*' })
-- e.g. GoTestFile unit
-- command! -nargs=* -complete=custom,v:lua.package.loaded.go.package_complete GoTestFile lua require('go.gotest').test_file(<f-args>)

@ -450,6 +450,27 @@ M.run = function(...)
testfunc = require('go.gotest').get_test_func_name()
log(testfunc)
local tblcase_ns = require('go.gotest').get_testcase_name()
log(tblcase_ns)
if empty(tblcase_ns) then
vim.notify('put cursor on test case name string')
end
local tbl_name = ''
if tblcase_ns and tblcase_ns.name then
vim.notify('running test case: ' .. tblcase_ns.name)
tbl_name = tblcase_ns.name
tbl_name = tbl_name:gsub('"', '') -- remove "
tbl_name = tbl_name:gsub(' ', '_') -- remove space
tbl_name = tbl_name:gsub('/', '//')
tbl_name = tbl_name:gsub('%(', '\\(')
tbl_name = tbl_name:gsub('%)', '\\)')
tbl_name = '/' .. tbl_name
end
log(tblcase_ns)
if testfunc then
if testfunc.name ~= 'main' then
optarg['t'] = true
@ -465,7 +486,8 @@ M.run = function(...)
if testfunc.name:lower():find('bench') then
dap_cfg.args = { '-test.bench', '^' .. testfunc.name .. '$' }
else
dap_cfg.args = { '-test.run', '^' .. testfunc.name .. '$' }
dap_cfg.args = { "-test.run=^" .. testfunc.name .. "$" .. tbl_name }
-- dap_cfg.args = { [[-test.run=^TestTransactionCheckEngine_Check$/should_process]]}
end
end
dap.configurations.go = { dap_cfg }

@ -16,6 +16,7 @@ local long_opts = {
coverage = 'C',
count = 'n',
tags = 't',
fuzz = 'f',
bench = 'b',
metric = 'm',
select = 's',
@ -331,29 +332,33 @@ M.get_test_func_name = function()
return ns
end
--options {s:select, F: floaterm}
M.test_func = function(...)
local args = { ... }
log(args)
local ns = M.get_test_func_name()
M.get_testcase_name = function()
local row, col = unpack(vim.api.nvim_win_get_cursor(0))
row, col = row, col + 1
local ns = require('go.ts.go').get_testcase_node()
if empty(ns) then
return M.select_tests()
return nil
end
if ns == nil or ns.name == nil then
return nil
end
return ns
end
local function run_tests_with_ts_node(args, func_node, tblcase_ns)
local optarg, _, reminder = getopt.get_opts(args, short_opts, long_opts)
local tags = M.get_build_tags(args)
utils.log('tags: ', tags)
utils.log('parnode' .. vim.inspect(ns))
utils.log('parnode' .. vim.inspect(func_node))
local test_runner = _GO_NVIM_CFG.go
local test_runner = _GO_NVIM_CFG.test_runner or 'go'
if _GO_NVIM_CFG.test_runner ~= 'go' then
test_runner = _GO_NVIM_CFG.test_runner
if test_runner ~= 'go' then
if not install(test_runner) then
test_runner = 'go'
end
if test_runner == 'ginkgo' then
ginkgo.test_func(...)
ginkgo.test_func(unpack(args))
end
end
@ -376,22 +381,35 @@ M.test_func = function(...)
if tags and tags ~= '' then
table.insert(cmd, tags)
end
if ns == nil or ns.name == nil then
if func_node == nil or func_node.name == nil then
return
end
if optarg['n'] then
table.insert(cmd, '-count=' .. optarg['n'] or '1')
table.insert(cmd, '-count=' .. (optarg['n'] or '1'))
end
local tbl_name = ""
if tblcase_ns and tblcase_ns.name then
tbl_name = tblcase_ns.name:gsub('/', '//')
tbl_name = tbl_name:gsub('%(', '\\(')
tbl_name = tbl_name:gsub('%)', '\\)')
tbl_name = '/' .. tbl_name
end
if ns.name:find('Bench') then
local bench = '-bench=' .. ns.name
if func_node.name:find('Bench') then
local bench = '-bench=' .. func_node.name .. tbl_name
table.insert(cmd, bench)
vim.list_extend(cmd, bench_opts)
elseif func_node.name:find('Fuzz') then
table.insert(cmd, '-fuzz')
table.insert(cmd, func_node.name)
else
table.insert(cmd, run_flags)
table.insert(cmd, [['^]] .. ns.name .. [[$']])
table.insert(cmd, [['^]] .. func_node.name .. [[$']] .. tbl_name)
end
local fpath = get_test_path()
table.insert(cmd, fpath)
@ -401,11 +419,13 @@ M.test_func = function(...)
end
if test_runner == 'dlv' then
local runflag = string.format("-test.run='^%s$'%s", func_node.name, tbl_name)
if tags and #tags > 0 then
cmd = { 'dlv', 'test', fpath, '--build-flags', tags, '--', '-test.run', '^' .. ns.name }
cmd = { 'dlv', 'test', fpath, '--build-flags', tags, '--', runflag}
else
cmd = { 'dlv', 'test', fpath, '--', '-test.run', '^' .. ns.name }
cmd = { 'dlv', 'test', fpath, '--', runflag }
end
log(cmd)
local term = require('go.term').run
term({ cmd = cmd, autoclose = false })
return
@ -426,6 +446,36 @@ M.test_func = function(...)
utils.log('test cmd', cmd)
return require('go.asyncmake').make(unpack(cmd))
end
--options {s:select, F: floaterm}
M.test_func = function(...)
local args = { ... }
log(args)
local ns = M.get_test_func_name()
if empty(ns) then
return M.select_tests()
end
return run_tests_with_ts_node(args, ns)
end
--options {s:select, F: floaterm}
M.test_tblcase = function(...)
local args = { ... }
log(args)
local ns = M.get_test_func_name()
if empty(ns) then
vim.notify('put cursor on test case name string')
end
local tblcase_ns = M.get_testcase_name()
if empty(tblcase_ns) then
vim.notify('put cursor on test case name string')
end
return run_tests_with_ts_node(args, ns, tblcase_ns)
end
M.test_file = function(...)
@ -495,11 +545,11 @@ M.test_file = function(...)
if next(reminder) then
vim.list_extend(cmd_args, reminder)
end
table.insert(cmd_args, '-run')
if optarg['n'] then
table.insert(cmd_args, '-count=' .. optarg['n'] or '1')
end
table.insert(cmd_args, '-run')
local sh = vim.o.shell
if sh:find('fish') then

@ -101,6 +101,8 @@ local M = {
(#contains? @test_name "Test")
(#match? @_param_package "testing")
(#match? @_param_name "T"))]],
query_testcase_node = [[(literal_value (literal_element (literal_value .(keyed_element (literal_element (identifier)) (literal_element (interpreted_string_literal) @test.name)))))]],
query_string_literal = [[((interpreted_string_literal) @string.value)]],
}
local function get_name_defaults()
@ -172,6 +174,30 @@ M.get_func_method_node_at_pos = function(bufnr)
end
end
M.get_testcase_node = function(bufnr)
local query = M.query_testcase_node
local bufn = bufnr or vim.api.nvim_get_current_buf()
local ns = nodes.nodes_at_cursor(query, get_name_defaults(), bufn, 'name')
if ns == nil then
debug('test case not found')
else
log('testcase node', ns[#ns])
return ns[#ns]
end
end
M.get_string_node = function(bufnr)
local query = M.query_string_literal
local bufn = bufnr or vim.api.nvim_get_current_buf()
local ns = nodes.nodes_at_cursor(query, get_name_defaults(), bufn, 'value')
if ns == nil then
debug('struct not found')
else
log('struct node', ns[#ns])
return ns[#ns]
end
end
M.get_import_node_at_pos = function(bufnr)
local bufn = bufnr or vim.api.nvim_get_current_buf()

@ -119,7 +119,8 @@ M.get_nodes = function(query, lang, defaults, bufnr)
return results
end
M.get_all_nodes = function(query, lang, defaults, bufnr, pos_row, pos_col, type_only)
M.get_all_nodes = function(query, lang, defaults, bufnr, pos_row, pos_col, ntype)
ulog(query, lang, defaults, pos_row, pos_col)
bufnr = bufnr or 0
-- todo a huge number
pos_row = pos_row or 30000
@ -127,6 +128,7 @@ M.get_all_nodes = function(query, lang, defaults, bufnr, pos_row, pos_col, type_
return vim.treesitter.parse_query(lang, query)
end)
if not success then
ulog('failed to parse ts query: ' .. query .. 'for ' .. lang)
return nil
end
@ -143,6 +145,7 @@ M.get_all_nodes = function(query, lang, defaults, bufnr, pos_row, pos_col, type_
local name = ""
local op = ""
-- local method_receiver = ""
ulog(match)
locals.recurse_local_nodes(match, function(_, node, path)
-- local idx = string.find(path, ".", 1, true)
@ -171,7 +174,7 @@ M.get_all_nodes = function(query, lang, defaults, bufnr, pos_row, pos_col, type_
-- stylua: ignore end
--
-- may not handle complex node
if op == "name" then
if op == "name" or op == "value" or op == "definition" then
-- ulog("node name " .. name)
name = get_node_text(node, bufnr) or ""
type_node = node
@ -198,7 +201,7 @@ M.get_all_nodes = function(query, lang, defaults, bufnr, pos_row, pos_col, type_
type = node_type or type,
})
end
if type_node ~= nil and type_only then
if type_node ~= nil and ntype then
ulog("type_only")
sRow, sCol, eRow, eCol = ts_utils.get_vim_range({ ts_utils.get_node_range(type_node) }, bufnr)
table.insert(results, {
@ -231,20 +234,20 @@ M.nodes_in_buf = function(query, default, bufnr, row, col)
return nodes
end
M.nodes_at_cursor = function(query, default, bufnr)
M.nodes_at_cursor = function(query, default, bufnr, ntype)
local row, col = unpack(vim.api.nvim_win_get_cursor(0))
row, col = row, col + 1
bufnr = bufnr or vim.api.nvim_get_current_buf()
local ft = vim.api.nvim_buf_get_option(bufnr, "ft")
local nodes = M.get_all_nodes(query, ft, default, bufnr, row, col)
local nodes = M.get_all_nodes(query, ft, default, bufnr, row, col, ntype)
if nodes == nil then
vim.notify("Unable to find any nodes. place your cursor on a go symbol and try again", vim.lsp.log_levels.DEBUG)
ulog("Unable to find any nodes. place your cursor on a go symbol and try again")
return nil
end
ulog(#nodes)
local nodes_at_cursor = M.sort_nodes(M.intersect_nodes(nodes, row, col))
ulog(nodes, row, col, nodes_at_cursor)
ulog(row, col, vim.inspect(nodes_at_cursor):sub(1, 100))
if nodes_at_cursor == nil or #nodes_at_cursor == 0 then
vim.notify("Unable to find any nodes at pos. " .. tostring(row) .. ":" .. tostring(col), vim.lsp.log_levels.DEBUG)
ulog("Unable to find any nodes at pos. " .. tostring(row) .. ":" .. tostring(col))

Loading…
Cancel
Save