rcasia / neotest-java

Neotest adapter for Java.
MIT License
45 stars 25 forks source link

Fix running tests in multi-project builds #100

Closed JonaLoeffler closed 2 months ago

JonaLoeffler commented 7 months ago

With the latest plugin version, running tests in my multi-project gradle build fails.

The project consists of a number gradle sub-projects like com.company.app.web.server.<component> for about 10 components. Each of these then has src/test/java.

cat: build/neotest-java/classpath.txt: No such file or directory
error: --class-path requires an argument
Usage: javac <options> <source files>
use --help for a list of possible options

The statusline briefly shows src/test/java is not accessible by the current user!, then Error reading file: /tmp/neotest-java/<some kind of id>/TEST-junit-jupiter.xml

This is my Lazy config for neotest:

return {
  {
    'rcasia/neotest-java',
    ft = 'java',
    dependencies = {
      'nvim-neotest/neotest',
      dependencies = {
        'nvim-neotest/nvim-nio',
        'nvim-lua/plenary.nvim',
        'antoinemadec/FixCursorHold.nvim',
        'nvim-treesitter/nvim-treesitter',
      },
    },
    config = function()
      require('neotest').setup {
        adapters = {
          require 'neotest-java' {
            ignore_wrapper = false, -- whether to ignore maven/gradle wrapper
          },
        },
      }

      vim.keymap.set('n', '<leader>tp', function()
        require('neotest').run.run(vim.uv.cwd())
      end, { desc = '[T]est [P]project', noremap = true })

      vim.keymap.set('n', '<leader>tf', function()
        require('neotest').run.run(vim.fn.expand '%')
      end, { desc = '[T]est [F]ile', noremap = true })

      vim.keymap.set('n', '<leader>tr', function()
        require('neotest').run.run()
      end, { desc = '[T]est [R]un', noremap = true })

      vim.keymap.set('n', '<leader>ts', function()
        require('neotest').run.stop()
      end, { desc = '[T]est [S]top', noremap = true })

      vim.keymap.set('n', '<leader>ta', function()
        require('neotest').run.attach()
      end, { desc = '[T]est [A]ttach', noremap = true })

      vim.keymap.set('n', '<leader>to', function()
        require('neotest').output.open()
      end, { desc = '[T]est output [O]pen', noremap = true })
    end,
  },
}

build/neotest-java/classpath.txt does exist in the working directory, but is empty.

Version v.1.10.0 still works as before.

steffsommer commented 3 months ago

This might be the biggest blocker for people to use this plugin in real world settings

steffsommer commented 2 months ago

I created a related issue with potential solutions, which was moved to discussions. I am linking it here for reference: https://github.com/rcasia/neotest-java/discussions/149

rcasia commented 2 months ago

Sorry for the latency, I had no much time for it. I just merged the feature https://github.com/rcasia/neotest-java/commit/9e6e8cf630d32d620700c4fbcf489e18292600ec.

I'll close this issue but feel completely free to reopen! :call_me_hand:

LorenzoBettini commented 1 month ago

I seem to understand that multi module projects are supported, but is it only the case for Gradle projects. With a few Maven multi module projects I tried it doesn't work.

rcasia commented 1 month ago

Hi @LorenzoBettini, do you have any examples?

LorenzoBettini commented 1 month ago

@rcasia this a minimal example https://github.com/LorenzoBettini/maven-multimodule-example

rcasia commented 1 month ago

this a minimal example https://github.com/LorenzoBettini/maven-multimodule-example

This project is using Junit4, which currently is not supported.

LorenzoBettini commented 1 month ago

Not supported in a multi project? Because in a single project it works: it detects all the tests in a single project using junit4.

rcasia commented 1 month ago

Not supported in a multi project? Because in a single project it works: it detects all the tests in a single project using junit4.

Sorry, you are right.

Junit4 is supported, but not junit4 with the format of the old junit3 which is being implemented here: https://github.com/LorenzoBettini/maven-multimodule-example/blob/master/my-app-parent/my-app-module1/src/test/java/org/my/app/module1/AppTest.

The main incompatibility between neotest-java and junit3 format is that the test methods don't have the Test annotation class, so they will not be detected to be run.

LorenzoBettini commented 1 month ago

@rcasia sorry, I had forgotten I had created those example projects with an old version of the Maven archetype that generates JUnit 3 tests.

I've update the example https://github.com/LorenzoBettini/maven-multimodule-example/commit/508e6acdf5d2b49dbffda1def0155affabe6e57b

Still I don't understand how it is meant to work.

If I start Neovim from the parent directory my-app-parent, I see that the summary detected the tests in the submodules:

image

However, If I try to run it from there selecting a testclass and press r, I get this error

Error executing vim.schedule lua callback: ...ava/lazy/neotest-java/lua/neotest-java/command/jdtls.lua:18: {
  code = -32001,
  data = {
    message = "my-app-parent does not exist"
  },
  message = "my-app-parent does not exist",
  <metatable> = {
    __tostring = <function 1>
  }
}
stack traceback:
    [C]: in function 'assert'
    ...ava/lazy/neotest-java/lua/neotest-java/command/jdtls.lua:18: in function 'handler'
    .../neovim/0.10.0/share/nvim/runtime/lua/vim/lsp/client.lua:685: in function ''
    vim/_editor.lua: in function <vim/_editor.lua:0>

If I try to run all tests with :lua require("neotest").run.run(vim.uv.cwd()), I get

neotest-java: ....local/share/lazyvim-java/lazy/nvim-nio/lua/nio/init.lua:119: The coroutine failed with this message: 
...zy/neotest-java/lua/neotest-java/core/result_builder.lua:71: there was an error while running command
stack traceback:
    [C]: in function 'assert'
    ...zy/neotest-java/lua/neotest-java/core/result_builder.lua:71: in function 'results'
    .../lazyvim-java/lazy/neotest/lua/neotest/client/runner.lua:132: in function '_run_spec'
    .../lazyvim-java/lazy/neotest/lua/neotest/client/runner.lua:89: in function <.../lazyvim-java/lazy/neotest/lua/neotest/client/runner.lua:88>
stack traceback:
    ...re/lazyvim-java/lazy/neotest/lua/neotest/client/init.lua:89: in function <...re/lazyvim-java/lazy/neotest/lua/neotest/client/init.lua:88>
    [C]: in function 'error'
    ....local/share/lazyvim-java/lazy/nvim-nio/lua/nio/init.lua:119: in function 'gather'
    .../lazyvim-java/lazy/neotest/lua/neotest/client/runner.lua:94: in function '_run_tree'
    .../lazyvim-java/lazy/neotest/lua/neotest/client/runner.lua:65: in function <.../lazyvim-java/lazy/neotest/lua/neotest/client/runner.lua:22>
    [C]: in function 'xpcall'
    ...re/lazyvim-java/lazy/neotest/lua/neotest/client/init.lua:84: in function 'run_tree'
    .../lazyvim-java/lazy/neotest/lua/neotest/consumers/run.lua:85: in function 'func'
    ...local/share/lazyvim-java/lazy/nvim-nio/lua/nio/tasks.lua:173: in function <...local/share/lazyvim-java/lazy/nvim-nio/lua/nio/tasks.lua:172>

It only works if I start Neovim from one of the submodules' directory, e.g., my-app-module1. Of course, I can only run the tests in that project.

Without quitting Neovim, I can use :lcd to switch to another directory, e.g., :lcd ../my-app-module2, and then run :lua require("neotest").run.run(vim.uv.cwd()) to run the tests in the other project (the new current working directory). But then, the summary is not usable anymore: if I try to re-run one of the tests with r it says no Jdtls client attached. And the summary shows it runs without terminating. Sometimes, in this case, it also shows:

neotest-java: ...lazy/neotest-java/lua/neotest-java/core/spec_builder.lua:62: module base_dir not found
stack traceback:
    ...re/lazyvim-java/lazy/neotest/lua/neotest/client/init.lua:89: in function <...re/lazyvim-java/lazy/neotest/lua/neotest/client/init.lua:88>
    [C]: in function 'assert'
    ...lazy/neotest-java/lua/neotest-java/core/spec_builder.lua:62: in function 'build_spec'
    .../lazyvim-java/lazy/neotest/lua/neotest/client/runner.lua:76: in function '_run_tree'
    .../lazyvim-java/lazy/neotest/lua/neotest/client/runner.lua:65: in function <.../lazyvim-java/lazy/neotest/lua/neotest/client/runner.lua:22>
    [C]: in function 'xpcall'
    ...re/lazyvim-java/lazy/neotest/lua/neotest/client/init.lua:84: in function 'run_tree'
    .../lazyvim-java/lazy/neotest/lua/neotest/consumers/run.lua:85: in function 'func'
    ...local/share/lazyvim-java/lazy/nvim-nio/lua/nio/tasks.lua:173: in function <...local/share/lazyvim-java/lazy/nvim-nio/lua/nio/tasks.lua:172>

Maybe I don't understand how it is supposed to work...