Skip to content

Test Management

Tobias Zimmermann edited this page Aug 18, 2022 · 2 revisions

Simple config

By default the lsp.create_test function will create a test class which simply contains the package and a the class declaration.

This can be configured using the test.class_snippets table.

require("java_util").setup({
  test = {
    use_defaults = false, -- Setting this to false will make sure you don't get the default class snippet.
    class_snippets = {
      ["You snippet name"] = function(info)
        return string.format(
          [[
package %s;

public class %s {
    // Whatever you want in here
}]],
          info.package,
          info.classname
        )
      end,
    },
  },

Now when you create a test, it will use your snippet instead of the default.

You can create as many class snippets as you want. Ones you have more than one, it will simply prompt you to select a snippet to use before creating it.

Using LuaSnip

Instead of returning a string from your class snippet, you can simply return a luasnip snippet. This will then be executed in the test file.

require("java_util").setup({
  -- ...
  class_snippets = {
    ["Your snippet name"] = function(info)
      return require("luasnip").parser.parse_snippet( -- Any luasnip snippet would work
            "_", -- Name doens't matter
            string.format(
              [[
package %s;

import org.junit.jupiter.api.Test;

public class %s {

    $Test
    void $1() {
      $0
    }
}]],
              info.package,
              info.classname
            )
          )
    end,
  },
  --- ...
},

Functions After Snippet Insertion

We expose an test.after_snippet function which you can setup to do whatever. This could things like notifying some event, or runnig functions based on what is generated.

Example Organize Imports

If you are using nvim_jdtls you will have access to an organize_imports function. We can use this to remove the need of manually writing the imports when creating the snippet.

If you are not using luasnip this is as simple as doing:

require("java_util").setup({
  -- ...
  after_snippet = function(info)
    require("jdtls").organize_imports()

    -- or if you dont always want it:

    if info.snippet == "Do organize this" then
      require("jdtls").organize_imports()
    end
  end
  -- ...
})

If you are using luasnip this becomes a bit more difficult, because using something like ${1:testname}] will put you into select mode, but running organize_imports will put you out of it and create some weird highlighting.

To fix this one solution could look something like this.

local function feedkeys(keys, opts)
  local replaced = vim.api.nvim_replace_termcodes(keys, true, false, true)
  vim.api.nvim_feedkeys(replaced, opts or "n", true)
end

require("java_util").setup({
  -- ...
  after_snippet = function(opts)
    require("jdtls").organize_imports()
    if opts.is_luasnip then
      vim.defer_fn(function()
        local mode = vim.fn.mode()
        if mode == "n" then
          feedkeys("a") -- Running organize_imports will put you in normal mode, so just go back to insert mode
        elseif mode == "s" then
          feedkeys("<esc>evb<C-G>") -- Remove everything selected -> rehighlight word -> go into select mode
        end
      end, 300) -- This could maybe be adjusted according to what works for you. It just needs to wait until the organize_imports is completed
    end
  end
  -- ...
})

Going to Tests

By default the lsp.goto_test will either go to a a test or the implementation of the test you are currently in.

The function optionally takes in a some options which allows you to configure how you want it to work.

Create Test if None are Found

require("java_util.lsp").goto_test({
  on_no_results = function (opts)
    require("java_util.lsp").create_test()
    -- or require("java_util.lsp").create_test({ testname = string.format("%sTest", opts.current_class) }) if you don't want a popup to choose a name
  end
})

Find All Tests

require("java_util.lsp").goto_test({
  current_class = ""
})