mirror of
https://github.com/mfussenegger/nvim-jdtls
synced 2024-09-16 14:34:13 +02:00
Add test result parsing and display via diagnostic for testng
This commit is contained in:
parent
697b39e3db
commit
3ca419c52a
2 changed files with 178 additions and 16 deletions
|
@ -123,7 +123,7 @@ local TestLevel = {
|
|||
}
|
||||
|
||||
|
||||
local function make_junit_request_args(lens, uri)
|
||||
local function make_request_args(lens, uri)
|
||||
local methodname = ''
|
||||
local name_parts = vim.split(lens.fullName, '#')
|
||||
local classname = name_parts[1]
|
||||
|
@ -227,7 +227,7 @@ end
|
|||
|
||||
|
||||
local function fetch_launch_args(lens, context, on_launch_args)
|
||||
local req_arguments = make_junit_request_args(lens, context.uri)
|
||||
local req_arguments = make_request_args(lens, context.uri)
|
||||
local cmd_junit_args = {
|
||||
command = 'vscode.java.test.junit.argument';
|
||||
arguments = { vim.fn.json_encode(req_arguments) };
|
||||
|
@ -308,6 +308,29 @@ local function get_first_class_lens(lenses)
|
|||
end
|
||||
end
|
||||
|
||||
--- Return path to com.microsoft.java.test.runner-jar-with-dependencies.jar if found in bundles
|
||||
---
|
||||
---@return string? path
|
||||
local function testng_runner()
|
||||
local vscode_runner = 'com.microsoft.java.test.runner-jar-with-dependencies.jar'
|
||||
local client = get_clients({name='jdtls'})[1]
|
||||
local bundles = client and client.config.init_options.bundles or {}
|
||||
for _, jar_path in pairs(bundles) do
|
||||
local parts = vim.split(jar_path, '/')
|
||||
if parts[#parts] == vscode_runner then
|
||||
return jar_path
|
||||
end
|
||||
local basepath = vim.fs.dirname(jar_path)
|
||||
if basepath then
|
||||
for name, _ in vim.fs.dir(basepath) do
|
||||
if name == vscode_runner then
|
||||
return vim.fs.joinpath(basepath, name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function make_config(lens, launch_args, config_overrides)
|
||||
local config = {
|
||||
|
@ -324,14 +347,25 @@ local function make_config(lens, launch_args, config_overrides)
|
|||
}
|
||||
config = vim.tbl_extend('force', config, config_overrides or default_config_overrides)
|
||||
if lens.testKind == TestKind.TestNG or lens.kind == TestKind.TestNG then
|
||||
config.mainClass = 'org.testng.TestNG'
|
||||
-- id is in the format <project>@<class>#<method>
|
||||
local parts = vim.split(lens.id, '@')
|
||||
parts = vim.split(parts[2], '#')
|
||||
if #parts > 1 then
|
||||
config.args = string.format('-testclass %s -methods %s.%s', parts[1], parts[1], parts[2])
|
||||
local jar = testng_runner()
|
||||
if jar then
|
||||
config.mainClass = 'com.microsoft.java.test.runner.Launcher'
|
||||
config.args = string.format('testng %s', lens.fullName)
|
||||
table.insert(config.classPaths, jar);
|
||||
else
|
||||
config.args = string.format('-testclass %s', parts[1])
|
||||
local msg = (
|
||||
"Using basic TestNG integration. "
|
||||
.. "For better test results add com.microsoft.java.test.runner-jar-with-dependencies.jar to one of the `bundles` folders")
|
||||
vim.notify(msg)
|
||||
config.mainClass = 'org.testng.TestNG'
|
||||
-- id is in the format <project>@<class>#<method>
|
||||
local parts = vim.split(lens.id, '@')
|
||||
parts = vim.split(parts[2], '#')
|
||||
if #parts > 1 then
|
||||
config.args = string.format('-testclass %s -methods %s.%s', parts[1], parts[1], parts[2])
|
||||
else
|
||||
config.args = string.format('-testclass %s', parts[1])
|
||||
end
|
||||
end
|
||||
else
|
||||
config.args = table.concat(launch_args.programArguments, ' ');
|
||||
|
@ -340,6 +374,7 @@ local function make_config(lens, launch_args, config_overrides)
|
|||
end
|
||||
|
||||
|
||||
|
||||
---@param bufnr? integer
|
||||
---@return JdtDapContext
|
||||
local function make_context(bufnr)
|
||||
|
@ -378,19 +413,47 @@ local function run(lens, config, context, opts)
|
|||
config = vim.tbl_extend('force', config, opts.config or {})
|
||||
local test_results
|
||||
local server = nil
|
||||
local junit = require('jdtls.junit')
|
||||
|
||||
if lens.kind == TestKind.TestNG then
|
||||
dap.run(config, {
|
||||
after = function()
|
||||
if lens.kind == TestKind.TestNG or lens.testKind == TestKind.TestNG then
|
||||
local testng = require('jdtls.testng')
|
||||
local run_opts = {}
|
||||
if config.mainClass == "com.microsoft.java.test.runner.Launcher" then
|
||||
function run_opts.before(conf)
|
||||
server = assert(uv.new_tcp(), "uv.new_tcp() must return handle")
|
||||
test_results = testng.mk_test_results(context.bufnr)
|
||||
server:bind('127.0.0.1', 0)
|
||||
server:listen(128, function(err2)
|
||||
assert(not err2, err2)
|
||||
local sock = assert(vim.loop.new_tcp(), "uv.new_tcp must return handle")
|
||||
server:accept(sock)
|
||||
sock:read_start(test_results.mk_reader(sock))
|
||||
end)
|
||||
conf.args = string.format('%s %s', server:getsockname().port, conf.args)
|
||||
return conf
|
||||
end
|
||||
|
||||
function run_opts.after()
|
||||
if server then
|
||||
server:shutdown()
|
||||
server:close()
|
||||
end
|
||||
test_results.show(lens, context)
|
||||
if opts.after_test then
|
||||
opts.after_test()
|
||||
end
|
||||
end
|
||||
})
|
||||
else
|
||||
function run_opts.after()
|
||||
if opts.after_test then
|
||||
opts.after_test()
|
||||
end
|
||||
end
|
||||
end
|
||||
dap.run(config, run_opts)
|
||||
return
|
||||
end
|
||||
|
||||
local junit = require('jdtls.junit')
|
||||
dap.run(config, {
|
||||
before = function(conf)
|
||||
server = assert(uv.new_tcp(), "uv.new_tcp() must return handle")
|
||||
|
@ -406,8 +469,10 @@ local function run(lens, config, context, opts)
|
|||
return conf
|
||||
end;
|
||||
after = function()
|
||||
server:shutdown()
|
||||
server:close()
|
||||
if server then
|
||||
server:shutdown()
|
||||
server:close()
|
||||
end
|
||||
local items = test_results.show()
|
||||
maybe_repeat(lens, config, context, opts, items)
|
||||
if opts.after_test then
|
||||
|
|
97
lua/jdtls/testng.lua
Normal file
97
lua/jdtls/testng.lua
Normal file
|
@ -0,0 +1,97 @@
|
|||
local ns = vim.api.nvim_create_namespace('testng')
|
||||
local M = {}
|
||||
|
||||
local function parse(content, tests)
|
||||
local lines = vim.split(content, '\n')
|
||||
for _, line in ipairs(lines) do
|
||||
if vim.startswith(line, '@@<TestRunner-') then
|
||||
line = line.sub(line, 15)
|
||||
line = line:sub(1, -13)
|
||||
local test = vim.json.decode(line)
|
||||
if test.name ~= 'testStarted' then
|
||||
table.insert(tests, test)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
M.__parse = parse
|
||||
|
||||
|
||||
local function mk_buf_loop(sock, handle_buffer)
|
||||
local buffer = ''
|
||||
return function(err, chunk)
|
||||
assert(not err, err)
|
||||
if chunk then
|
||||
buffer = buffer .. chunk
|
||||
else
|
||||
sock:close()
|
||||
handle_buffer(buffer)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function M.mk_test_results(bufnr)
|
||||
vim.api.nvim_buf_clear_namespace(bufnr, ns, 0, -1)
|
||||
local tests = {}
|
||||
local handle_buffer = function(buf)
|
||||
parse(buf, tests)
|
||||
end
|
||||
local function get_test_line_nr(lenses, name)
|
||||
if lenses.fullName == name then
|
||||
return lenses.range.start.line
|
||||
end
|
||||
for _, v in ipairs(lenses) do
|
||||
if v.fullName == name then
|
||||
return v.range.start.line
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
return {
|
||||
show = function(lens)
|
||||
local repl = require('dap.repl')
|
||||
|
||||
-- error = '✘',
|
||||
-- warn = '▲',
|
||||
-- hint = '⚑',
|
||||
-- info = '»'
|
||||
local lenses = lens.children or lens
|
||||
local failed = {}
|
||||
for _, test in ipairs(tests) do
|
||||
local lnum = get_test_line_nr(lenses, test.attributes.name)
|
||||
if lnum ~= nil then
|
||||
local testName = vim.split(test.attributes.name, '#')[2]
|
||||
local message = test.attributes.message or 'test failed'
|
||||
if test.name == 'testFailed' then
|
||||
table.insert(failed, {
|
||||
bufnr = bufnr,
|
||||
lnum = lnum,
|
||||
col = 0,
|
||||
severity = vim.diagnostic.severity.ERROR,
|
||||
source = 'testng',
|
||||
message = message,
|
||||
user_data = {}
|
||||
})
|
||||
repl.append('❌ ' .. testName .. ' failed')
|
||||
repl.append(message)
|
||||
repl.append(test.attributes.trace)
|
||||
elseif test.name == 'testFinished' then
|
||||
local text = { '✔️ ' }
|
||||
vim.api.nvim_buf_set_extmark(bufnr, ns, lnum, 0, {
|
||||
virt_text = { text },
|
||||
})
|
||||
repl.append('✔️ ' .. testName .. ' passed')
|
||||
end
|
||||
end
|
||||
end
|
||||
vim.diagnostic.set(ns, bufnr, failed, {})
|
||||
end,
|
||||
mk_reader = function(sock)
|
||||
return vim.schedule_wrap(mk_buf_loop(sock, handle_buffer))
|
||||
end,
|
||||
}
|
||||
end
|
||||
|
||||
return M
|
Loading…
Reference in a new issue