Skip to content

Commit

Permalink
refactor: variable naming
Browse files Browse the repository at this point in the history
  • Loading branch information
fredrikaverpil committed Jun 15, 2024
1 parent 3006146 commit d2dc213
Showing 1 changed file with 95 additions and 71 deletions.
166 changes: 95 additions & 71 deletions lua/neotest-golang/results_dir.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,16 @@ local json = require("neotest-golang.json")
local utils = require("neotest-golang.utils")

--- @class InternalResult
--- @field neotest_position neotest.Position
--- @field status neotest.ResultStatus
--- @field output? string[] Go test output.
--- @field short? string Shortened output string
--- @field errors? neotest.Error[]
--- @field neotest_node_data neotest.Position
--- @field go_test_data GoTestData
--- @field gotest_data GoTestData
--- @field duplicate_test_detected boolean

--- @class GoTestData
--- @field name string
--- @field package string
--- @field output? string[] Go test output.

local M = {}

Expand All @@ -35,11 +34,11 @@ function M.results(spec, result, tree)

--- Internal data structure to store test results.
--- @type table<string, InternalResult>
local d = M.aggregate_data(tree, gotest_output)
local res = M.aggregate_data(tree, gotest_output)

M.show_warnings(d)
M.show_warnings(res)

local neotest_results = M.to_neotest_results(spec, result, d, gotest_output)
local neotest_results = M.to_neotest_results(spec, result, res, gotest_output)

-- FIXME: once output is parsed, erase file contents, so to avoid JSON in
-- output panel. This is a workaround for now, only because of
Expand All @@ -57,10 +56,10 @@ end
--- @param gotest_output table
--- @return table<string, InternalResult>
function M.aggregate_data(tree, gotest_output)
local d = M.gather_neotest_data_and_set_defaults(tree)
d = M.decorate_with_go_package_and_test_name(d, gotest_output)
d = M.decorate_with_go_test_results(d, gotest_output)
return d
local res = M.gather_neotest_data_and_set_defaults(tree)
res = M.decorate_with_go_package_and_test_name(res, gotest_output)
res = M.decorate_with_go_test_results(res, gotest_output)
return res
end

--- Generate the internal data which will be used by neotest-golang before.
Expand All @@ -70,7 +69,7 @@ end
function M.gather_neotest_data_and_set_defaults(tree)
--- Internal data structure to store test results.
--- @type table<string, InternalResult>
local d = {}
local res = {}

--- Table storing the name of the test (position.id) and the number of times
--- it was found in the tree.
Expand All @@ -82,59 +81,59 @@ function M.gather_neotest_data_and_set_defaults(tree)
local pos = node:data()

if pos.type == "test" then
d[pos.id] = {
status = "skipped", -- default
output = {}, -- default -- TODO: move into go_test_data
errors = {}, -- default -- TODO: move into go_test_data
neotest_node_data = pos, -- TODO: rename to neotest_position_data
go_test_data = {
name = "", -- default
package = "", -- default
}, -- default
duplicate_test_detected = false, -- default
res[pos.id] = {
status = "skipped",
errors = {},
neotest_position = pos,
gotest_data = {
name = "",
package = "",
output = {},
},
duplicate_test_detected = false,
}

-- detect duplicate test names
if dupes[pos.id] == nil then
dupes[pos.id] = 1
else
dupes[pos.id] = dupes[pos.id] + 1
d[pos.id].duplicate_test_detected = true
res[pos.id].duplicate_test_detected = true
end
end
end
return d
return res
end

--- Decorate the internal results with go package and test name.
--- This is an important step to associate the test results with the tree nodes
--- as the 'go test' JSON output contains keys 'Package' and 'Test'.
--- @param d table<string, InternalResult>
--- @param res table<string, InternalResult>
--- @param gotest_output table
--- @return table<string, InternalResult>
function M.decorate_with_go_package_and_test_name(d, gotest_output)
for pos_id in pairs(d) do
function M.decorate_with_go_package_and_test_name(res, gotest_output)
for pos_id in pairs(res) do
for _, line in ipairs(gotest_output) do
if line.Action == "run" and line.Test ~= nil then
local folderpath =
vim.fn.fnamemodify(d[pos_id].neotest_node_data.path, ":h")
vim.fn.fnamemodify(res[pos_id].neotest_position.path, ":h")
local match = nil
local common_path = utils.find_common_path(line.Package, folderpath)

if common_path ~= "" then
local tweaked_neotest_node_id = pos_id:gsub(" ", "_")
tweaked_neotest_node_id = tweaked_neotest_node_id:gsub('"', "")
tweaked_neotest_node_id = tweaked_neotest_node_id:gsub("::", "/")
local tweaked_pos_id = pos_id:gsub(" ", "_")
tweaked_pos_id = tweaked_pos_id:gsub('"', "")
tweaked_pos_id = tweaked_pos_id:gsub("::", "/")

local combined_pattern = convert.to_lua_pattern(common_path)
.. "/(.-)/"
.. convert.to_lua_pattern(line.Test)
.. "$"

match = tweaked_neotest_node_id:match(combined_pattern)
match = tweaked_pos_id:match(combined_pattern)
end
if match ~= nil then
d[pos_id].go_test_data = {
res[pos_id].gotest_data = {
package = line.Package,
name = line.Test,
}
Expand All @@ -144,34 +143,36 @@ function M.decorate_with_go_package_and_test_name(d, gotest_output)
end
end

return d
return res
end

--- Decorate the internal results with data from the 'go test' output.
--- @param d table<string, InternalResult>
--- @param res table<string, InternalResult>
--- @param gotest_output table
--- @return table<string, InternalResult>
function M.decorate_with_go_test_results(d, gotest_output)
for pos_id in pairs(d) do
function M.decorate_with_go_test_results(res, gotest_output)
for pos_id in pairs(res) do
for _, line in ipairs(gotest_output) do
if
d[pos_id].go_test_data.package == line.Package
and d[pos_id].go_test_data.name == line.Test
res[pos_id].gotest_data.package == line.Package
and res[pos_id].gotest_data.name == line.Test
then
-- record test status
-- test matched, let's record some data and decorate the internal
-- results with it.

if line.Action == "pass" then
d[pos_id].status = "passed"
res[pos_id].status = "passed"
elseif line.Action == "fail" then
d[pos_id].status = "failed"
res[pos_id].status = "failed"
elseif line.Action == "output" then
-- append line.Output to output field
d[pos_id].output = vim.list_extend(d[pos_id].output, { line.Output })
res[pos_id].gotest_data.output =
vim.list_extend(res[pos_id].gotest_data.output, { line.Output })

-- determine test filename
local test_filename = "_test.go" -- approximate test filename
if d[pos_id].neotest_node_data ~= nil then
if res[pos_id].neotest_position ~= nil then
-- node data is available, get the exact test filename
local test_filepath = d[pos_id].neotest_node_data.path
local test_filepath = res[pos_id].neotest_position.path
test_filename = vim.fn.fnamemodify(test_filepath, ":t")
end

Expand All @@ -183,7 +184,7 @@ function M.decorate_with_go_test_results(d, gotest_output)
local message =
string.match(line.Output, test_filename .. ":%d+: (.*)")
if line_number ~= nil and message ~= nil then
table.insert(d[pos_id].errors, {
table.insert(res[pos_id].errors, {
line = line_number - 1, -- neovim lines are 0-indexed
message = message,
})
Expand All @@ -193,17 +194,17 @@ function M.decorate_with_go_test_results(d, gotest_output)
end
end
end
return d
return res
end

--- Show warnings.
--- @param d table<string, InternalResult>
--- @param res table<string, InternalResult>
--- @return nil
function M.show_warnings(d)
function M.show_warnings(res)
-- warn if Go package/test is missing from tree node.
-- TODO: make configurable to skip this or use different log level?
for pos_id in pairs(d) do
if d[pos_id].go_test_data.name == "" then
for pos_id in pairs(res) do
if res[pos_id].gotest_data.name == "" then
vim.notify(
"Unable to associate go package/test with neotest tree node: " .. pos_id,
vim.log.levels.WARN
Expand All @@ -215,14 +216,13 @@ function M.show_warnings(d)

-- warn about duplicate tests
-- TODO: make debug level configurable
for pos_id in pairs(d) do
local test_data = d[pos_id]
if test_data.duplicate_test_detected == true then
for pos_id in pairs(res) do
if res[pos_id].duplicate_test_detected == true then
vim.notify(
"Duplicate test name detected: "
.. test_data.go_test_data.package
.. res[pos_id].gotest_data.package
.. "/"
.. test_data.go_test_data.name,
.. res[pos_id].gotest_data.name,
vim.log.levels.WARN
)
end
Expand All @@ -232,27 +232,49 @@ end
--- Convert internal results to Neotest results.
--- @param spec neotest.RunSpec
--- @param result neotest.StrategyResult
--- @param d table<string, InternalResult>
--- @param res table<string, InternalResult>
--- @param gotest_output table
--- @return table<string, neotest.Result>
function M.to_neotest_results(spec, result, d, gotest_output)
--- Neotest results.
function M.to_neotest_results(spec, result, res, gotest_output)
--- Neotest result to ultimately hand back over to Neotest.
--- @type table<string, neotest.Result>
local neotest_results = {}
local neotest_result = {}

-- populate all test results onto the Neotest format.
for pos_id in pairs(d) do
local test_data = d[pos_id]
-- populate all test results onto the Neotest result format.
for pos_id in pairs(res) do
local test_output_path = vim.fs.normalize(async.fn.tempname())
async.fn.writefile(test_data.output, test_output_path)
neotest_results[pos_id] = {
status = test_data.status,
errors = test_data.errors,
async.fn.writefile(res[pos_id].gotest_data.output, test_output_path)
neotest_result[pos_id] = {
status = res[pos_id].status,
errors = res[pos_id].errors,
output = test_output_path, -- NOTE: could be slow when running many tests?
}
end

--- Test command (e.g. 'go test') status.
neotest_result = M.decorate_with_test_command_data(
spec,
result,
neotest_result,
gotest_output
)

return neotest_result
end

--- Decorate the Neotest results with the ultimate status code of the command
--- which executed, along with its full output.
--- @param spec neotest.RunSpec
--- @param result neotest.StrategyResult
--- @param neotest_results neotest.Result
--- @param gotest_output table
--- @return table<string, neotest.Result>
function M.decorate_with_test_command_data(
spec,
result,
neotest_results,
gotest_output
)
--- The status code of the command which executed all tests in the directory.
--- @type neotest.ResultStatus
local test_command_status = "skipped"
if result.code == 0 then
Expand All @@ -261,7 +283,8 @@ function M.to_neotest_results(spec, result, d, gotest_output)
test_command_status = "failed"
end

--- Full 'go test' output (parsed from JSON).
--- The full output associated with the command which executed all tests in
--- the directory.
--- @type table
local full_output = {}
local test_command_output_path = vim.fs.normalize(async.fn.tempname())
Expand All @@ -272,7 +295,8 @@ function M.to_neotest_results(spec, result, d, gotest_output)
end
async.fn.writefile(full_output, test_command_output_path)

-- register properties on the directory node that was run
-- Register the status and output of the command which executed all tests
-- in the directory.
neotest_results[spec.context.id] = {
status = test_command_status,
output = test_command_output_path,
Expand Down

0 comments on commit d2dc213

Please sign in to comment.