diff --git a/lua/neotest-golang/cmd.lua b/lua/neotest-golang/cmd.lua new file mode 100644 index 00000000..11465cc9 --- /dev/null +++ b/lua/neotest-golang/cmd.lua @@ -0,0 +1,109 @@ +--- Helper functions building the command to execute. + +local options = require("neotest-golang.options") + +local M = {} + +function M.build_golist_cmd(cwd) + -- call 'go list -json ./...' to get test file data + local go_list_command = { + "go", + "list", + "-json", + "./...", + } + local go_list_command_result = + vim.fn.system("cd " .. cwd .. " && " .. table.concat(go_list_command, " ")) + return go_list_command_result +end + +function M.build_gotest_cmd_for_dir(module_name) + local gotest = { + "go", + "test", + "-json", + } + + local required_go_test_args = { + module_name, + } + + local combined_args = vim.list_extend( + vim.deepcopy(options.get().go_test_args), + required_go_test_args + ) + local cmd = vim.list_extend(vim.deepcopy(gotest), combined_args) + + return cmd +end + +function M.build_gotestsum_cmd_for_dir(module_name, json_filepath) + local gotest = { "gotestsum" } + local gotestsum_json = { + "--jsonfile=" .. json_filepath, + "--", + } + + local required_go_test_args = { + module_name, + } + + local gotest_args = vim.list_extend( + vim.deepcopy(options.get().go_test_args), + required_go_test_args + ) + + local cmd = + vim.list_extend(vim.deepcopy(gotest), options.get().gotestsum_args) + cmd = vim.list_extend(vim.deepcopy(cmd), gotestsum_json) + cmd = vim.list_extend(vim.deepcopy(cmd), gotest_args) + + return cmd +end + +function M.build_gotest_cmd_for_test(test_folder_absolute_path, test_name) + --- @type table + local required_go_test_args = { test_folder_absolute_path, "-run", test_name } + + local gotest = { + "go", + "test", + "-json", + } + + local combined_args = vim.list_extend( + vim.deepcopy(options.get().go_test_args), + required_go_test_args + ) + local cmd = vim.list_extend(vim.deepcopy(gotest), combined_args) + return cmd +end + +function M.build_gotestsum_cmd_for_test( + test_folder_absolute_path, + test_name, + json_filepath +) + --- @type table + local required_go_test_args = { test_folder_absolute_path, "-run", test_name } + + local gotest = { "gotestsum" } + local gotestsum_json = { + "--jsonfile=" .. json_filepath, + "--", + } + + local gotest_args = vim.list_extend( + vim.deepcopy(options.get().go_test_args), + required_go_test_args + ) + + local cmd = + vim.list_extend(vim.deepcopy(gotest), options.get().gotestsum_args) + cmd = vim.list_extend(vim.deepcopy(cmd), gotestsum_json) + cmd = vim.list_extend(vim.deepcopy(cmd), gotest_args) + + return cmd +end + +return M diff --git a/lua/neotest-golang/runspec_dir.lua b/lua/neotest-golang/runspec_dir.lua index 515e5c33..bfd5b771 100644 --- a/lua/neotest-golang/runspec_dir.lua +++ b/lua/neotest-golang/runspec_dir.lua @@ -1,9 +1,11 @@ --- Helpers to build the command and context around running all tests of --- a Go module. +local async = require("neotest.async") + local options = require("neotest-golang.options") local json = require("neotest-golang.json") -local async = require("neotest.async") +local cmd = require("neotest-golang.cmd") local M = {} @@ -18,10 +20,6 @@ local M = {} function M.build(pos) local go_mod_filepath = M.find_file_upwards("go.mod", pos.path) - -- if go_mod_filepath == nil then - -- go_mod_filepath = M.find_file_upwards("go.work", pos.path) - -- end - -- if no go.mod file was found up the directory tree, until reaching $CWD, -- then we cannot determine the Go project root. if go_mod_filepath == nil then @@ -40,19 +38,8 @@ function M.build(pos) end local go_mod_folderpath = vim.fn.fnamemodify(go_mod_filepath, ":h") - local cwd = go_mod_folderpath - - -- call 'go list -json ./...' to get test file data - local go_list_command = { - "go", - "list", - "-json", - "./...", - } - local go_list_command_result = vim.fn.system( - "cd " .. go_mod_folderpath .. " && " .. table.concat(go_list_command, " ") - ) - local golist_output = json.process_golist_output(go_list_command_result) + local go_list_command = cmd.build_golist_cmd(go_mod_folderpath) + local golist_output = json.process_golist_output(go_list_command) -- find the go module that corresponds to the go_mod_folderpath local module_name = "./..." -- if no go module, run all tests at the $CWD @@ -63,7 +50,34 @@ function M.build(pos) end end - return M.build_dir_test_runspec(pos, cwd, golist_output, module_name) + --- The runner to use for running tests. + --- @type string + local runner = options.get().runner + + -- TODO: if gotestsum, check if it is on $PATH, or fall back onto `go test` + + --- The filepath to write test output JSON to, if using `gotestsum`. + --- @type string | nil + local json_filepath = nil + + --- The final test command to execute. + --- @type table + local test_cmd = {} + + if runner == "go" then + test_cmd = cmd.build_gotest_cmd_for_dir(module_name) + elseif runner == "gotestsum" then + json_filepath = vim.fs.normalize(async.fn.tempname()) + test_cmd = cmd.build_gotestsum_cmd_for_dir(module_name, json_filepath) + end + + return M.build_runspec( + pos, + go_mod_folderpath, + test_cmd, + golist_output, + json_filepath + ) end --- Find a file upwards in the directory tree and return its path, if found. @@ -111,53 +125,13 @@ end --- Build runspec for a directory of tests --- @param pos neotest.Position --- @param cwd string +--- @param test_cmd table --- @param golist_output table ---- @param module_name string --- @return neotest.RunSpec | neotest.RunSpec[] | nil -function M.build_dir_test_runspec(pos, cwd, golist_output, module_name) - --- @type table - local required_go_test_args = { - module_name, - } - - local gotest_command = {} - local jsonfile = "" - - if options.get().runner == "go" then - local gotest = { - "go", - "test", - "-json", - } - - local combined_args = vim.list_extend( - vim.deepcopy(options.get().go_test_args), - required_go_test_args - ) - gotest_command = vim.list_extend(vim.deepcopy(gotest), combined_args) - elseif options.get().runner == "gotestsum" then - jsonfile = vim.fs.normalize(async.fn.tempname()) - local gotest = { "gotestsum" } - local gotestsum_json = { - "--jsonfile=" .. jsonfile, - "--", - } - local gotest_args = vim.list_extend( - vim.deepcopy(options.get().go_test_args), - required_go_test_args - ) - - local cmd = - vim.list_extend(vim.deepcopy(gotest), options.get().gotestsum_args) - cmd = vim.list_extend(vim.deepcopy(cmd), gotestsum_json) - cmd = vim.list_extend(vim.deepcopy(cmd), gotest_args) - - gotest_command = cmd - end - +function M.build_runspec(pos, cwd, test_cmd, golist_output, json_filepath) --- @type neotest.RunSpec local run_spec = { - command = gotest_command, + command = test_cmd, cwd = cwd, context = { id = pos.id, @@ -167,8 +141,8 @@ function M.build_dir_test_runspec(pos, cwd, golist_output, module_name) }, } - if jsonfile ~= nil then - run_spec.context.jsonfile = jsonfile + if json_filepath ~= nil then + run_spec.context.jsonfile = json_filepath end return run_spec diff --git a/lua/neotest-golang/runspec_test.lua b/lua/neotest-golang/runspec_test.lua index f922b957..78fb56ff 100644 --- a/lua/neotest-golang/runspec_test.lua +++ b/lua/neotest-golang/runspec_test.lua @@ -1,9 +1,11 @@ --- Helpers to build the command and context around running a single test. +local async = require("neotest.async") + local convert = require("neotest-golang.convert") local options = require("neotest-golang.options") local json = require("neotest-golang.json") -local async = require("neotest.async") +local cmd = require("neotest-golang.cmd") local M = {} @@ -14,68 +16,72 @@ local M = {} function M.build(pos, strategy) --- @type string local test_folder_absolute_path = string.match(pos.path, "(.+)/") - - -- call 'go list -json ./...' to get test file data - local go_list_command = { - "go", - "list", - "-json", - "./...", - } - local go_list_command_result = vim.fn.system( - "cd " - .. test_folder_absolute_path - .. " && " - .. table.concat(go_list_command, " ") - ) - local golist_output = json.process_golist_output(go_list_command_result) + local go_list_command = cmd.build_golist_cmd(test_folder_absolute_path) + local golist_output = json.process_golist_output(go_list_command) --- @type string local test_name = convert.to_gotest_test_name(pos.id) test_name = convert.to_gotest_regex_pattern(test_name) - --- @type table - local required_go_test_args = { test_folder_absolute_path, "-run", test_name } - - local gotest_command = {} - local jsonfile = "" - - if options.get().runner == "go" then - local gotest = { - "go", - "test", - "-json", - } - - local combined_args = vim.list_extend( - vim.deepcopy(options.get().go_test_args), - required_go_test_args - ) - gotest_command = vim.list_extend(vim.deepcopy(gotest), combined_args) - elseif options.get().runner == "gotestsum" then - jsonfile = vim.fs.normalize(async.fn.tempname()) - local gotest = { "gotestsum" } - local gotestsum_json = { - "--jsonfile=" .. jsonfile, - "--", - } - local gotest_args = vim.list_extend( - vim.deepcopy(options.get().go_test_args), - required_go_test_args + --- The runner to use for running tests. + --- @type string + local runner = options.get().runner + + -- TODO: if gotestsum, check if it is on $PATH, or fall back onto `go test` + + --- The filepath to write test output JSON to, if using `gotestsum`. + --- @type string | nil + local json_filepath = nil + + --- The final test command to execute. + --- @type table + local test_cmd = {} + + if runner == "go" then + test_cmd = + cmd.build_gotest_cmd_for_test(test_folder_absolute_path, test_name) + elseif runner == "gotestsum" then + json_filepath = vim.fs.normalize(async.fn.tempname()) + test_cmd = cmd.build_gotestsum_cmd_for_test( + test_folder_absolute_path, + test_name, + json_filepath ) - - local cmd = - vim.list_extend(vim.deepcopy(gotest), options.get().gotestsum_args) - cmd = vim.list_extend(vim.deepcopy(cmd), gotestsum_json) - cmd = vim.list_extend(vim.deepcopy(cmd), gotest_args) - - gotest_command = cmd end + return M.build_runspec( + pos, + test_folder_absolute_path, + test_cmd, + golist_output, + json_filepath, + strategy, + test_name + ) +end + +--- Build runspec for a directory of tests +--- @param pos neotest.Position +--- @param cwd string +--- @param test_cmd table +--- @param golist_output table +--- @param json_filepath string | nil +--- @param strategy string +--- @param test_name string +--- @return neotest.RunSpec | neotest.RunSpec[] | nil +function M.build_runspec( + pos, + cwd, + test_cmd, + golist_output, + json_filepath, + strategy, + test_name +) --- @type neotest.RunSpec local run_spec = { - command = gotest_command, - cwd = test_folder_absolute_path, + command = test_cmd, + cwd = cwd, context = { id = pos.id, test_filepath = pos.path, @@ -84,8 +90,8 @@ function M.build(pos, strategy) }, } - if jsonfile ~= nil then - run_spec.context.jsonfile = jsonfile + if json_filepath ~= nil then + run_spec.context.jsonfile = json_filepath end -- set up for debugging of test @@ -100,7 +106,7 @@ function M.build(pos, strategy) if dap_go_opts.delve == nil then dap_go_opts.delve = {} end - dap_go_opts.delve.cwd = test_folder_absolute_path + dap_go_opts.delve.cwd = cwd require("dap-go").setup(dap_go_opts) -- reset nvim-dap-go (and cwd) after debugging with nvim-dap