Skip to content

Commit

Permalink
feat(poc): gotestsum for readable output when attached
Browse files Browse the repository at this point in the history
  • Loading branch information
fredrikaverpil committed Jul 3, 2024
1 parent ee3156a commit 36fad2f
Show file tree
Hide file tree
Showing 5 changed files with 206 additions and 29 deletions.
8 changes: 3 additions & 5 deletions lua/neotest-golang/options.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@
local M = {}

local opts = {
go_test_args = {
"-v",
"-race",
"-count=1",
},
runner = "gotestsum", -- or "gotestsum"
go_test_args = { "-v", "-race", "-count=1" },
gotestsum_args = { "--format=standard-verbose" },
dap_go_enabled = false,
dap_go_opts = {},
warn_test_name_dupes = true,
Expand Down
9 changes: 7 additions & 2 deletions lua/neotest-golang/parse.lua
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,14 @@ function M.results(spec, result, tree)
--- @type neotest.Position
local pos = tree:data()

--- The raw output from the 'go test -json' command.
--- The raw output from the test command.
--- @type table
local raw_output = async.fn.readfile(result.output)
local raw_output = {}
if options.get().runner == "go" then
raw_output = async.fn.readfile(result.output)
elseif options.get().runner == "gotestsum" then
raw_output = async.fn.readfile(spec.context.jsonfile)
end

--- The 'go test' JSON output, converted into a lua table.
--- @type table
Expand Down
118 changes: 118 additions & 0 deletions lua/neotest-golang/results_test.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
local async = require("neotest.async")

local options = require("neotest-golang.options")
local convert = require("neotest-golang.convert")
local json = require("neotest-golang.json")

local M = {}

--- @async
--- @param spec neotest.RunSpec
--- @param result neotest.StrategyResult
--- @param tree neotest.Tree
--- @return table<string, neotest.Result>
function M.results(spec, result, tree)
---@type table<string, neotest.Result>
local results = {}
results[spec.context.id] = {
---@type neotest.ResultStatus
status = "skipped", -- default value
}

if spec.context.skip then
return results
end

--- @type boolean
local no_tests_to_run = false

--- The raw output from the test command.
--- @type table
local raw_output = {}
if options.get().runner == "go" then
raw_output = async.fn.readfile(result.output)
elseif options.get().runner == "gotestsum" then
raw_output = async.fn.readfile(spec.context.jsonfile)
end

--- @type string
local test_filepath = spec.context.test_filepath
local test_filename = vim.fn.fnamemodify(test_filepath, ":t")
--- @type table
local test_result = {}
--- @type neotest.Error[]
local errors = {}

--- @type table
local gotest_output = json.process_gotest_output(raw_output)

for _, line in ipairs(gotest_output) do
if line.Action == "output" and line.Output ~= nil then
-- record output, prints to output panel
table.insert(test_result, line.Output)

-- if test was not run, mark it as skipped

-- if line contains "no test files" or "no tests to run", mark as skipped
if string.match(line.Output, "no tests to run") then
no_tests_to_run = true
end
end

-- record an error
if result.code ~= 0 and line.Output ~= nil then
---@type string
local matched_line_number =
string.match(line.Output, test_filename .. ":(%d+):")

if matched_line_number ~= nil then
-- attempt to parse the line number...
---@type number | nil
local line_number = tonumber(matched_line_number)

if line_number ~= nil then
-- log the error along with its line number (for diagnostics)

---@type string
local message = string.match(line.Output, ":%d+: (.*)")

---@type neotest.Error
local error = {
message = message,
line = line_number - 1, -- neovim lines are 0-indexed
}
table.insert(errors, error)
end
end
end
end

if no_tests_to_run then
if options.get().warn_test_not_executed == true then
vim.notify(
"Could not execute test: "
.. convert.to_gotest_test_name(spec.context.id),
vim.log.levels.WARN
)
end
else
-- assign status code, as long as the test was found
if result.code == 0 then
results[spec.context.id].status = "passed"
else
results[spec.context.id].status = "failed"
end
end

-- write json_decoded to file
local parsed_output_path = vim.fs.normalize(async.fn.tempname())
async.fn.writefile(test_result, parsed_output_path)

---@type table<string, neotest.Result>
results[spec.context.id].output = parsed_output_path
results[spec.context.id].errors = errors

return results
end

return M
50 changes: 39 additions & 11 deletions lua/neotest-golang/runspec_dir.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

local options = require("neotest-golang.options")
local json = require("neotest-golang.json")
local async = require("neotest.async")

local M = {}

Expand Down Expand Up @@ -114,22 +115,45 @@ end
--- @param module_name string
--- @return neotest.RunSpec | neotest.RunSpec[] | nil
function M.build_dir_test_runspec(pos, cwd, golist_output, module_name)
local gotest = {
"go",
"test",
"-json",
}

--- @type table
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 gotest_command = vim.list_extend(vim.deepcopy(gotest), combined_args)
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

--- @type neotest.RunSpec
local run_spec = {
Expand All @@ -143,6 +167,10 @@ function M.build_dir_test_runspec(pos, cwd, golist_output, module_name)
},
}

if jsonfile ~= nil then
run_spec.context.jsonfile = jsonfile
end

return run_spec
end

Expand Down
50 changes: 39 additions & 11 deletions lua/neotest-golang/runspec_test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
local convert = require("neotest-golang.convert")
local options = require("neotest-golang.options")
local json = require("neotest-golang.json")
local async = require("neotest.async")

local M = {}

Expand Down Expand Up @@ -33,20 +34,43 @@ function M.build(pos, strategy)
local test_name = convert.to_gotest_test_name(pos.id)
test_name = convert.to_gotest_regex_pattern(test_name)

local gotest = {
"go",
"test",
"-json",
}

--- @type table
local required_go_test_args = { test_folder_absolute_path, "-run", test_name }

local combined_args = vim.list_extend(
vim.deepcopy(options.get().go_test_args),
required_go_test_args
)
local gotest_command = vim.list_extend(vim.deepcopy(gotest), combined_args)
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

--- @type neotest.RunSpec
local run_spec = {
Expand All @@ -60,6 +84,10 @@ function M.build(pos, strategy)
},
}

if jsonfile ~= nil then
run_spec.context.jsonfile = jsonfile
end

-- set up for debugging of test
if strategy == "dap" then
run_spec.strategy = M.get_dap_config(test_name)
Expand Down

0 comments on commit 36fad2f

Please sign in to comment.