neotest icon indicating copy to clipboard operation
neotest copied to clipboard

[BUG] No tests found if calling require("plenary.filetype") before Neotest does it

Open fredrikaverpil opened this issue 11 months ago • 10 comments

NeoVim Version

v0.11.1

Describe the bug

When another plugin calls require("plenary.filetype") before Neotest does, it seems that Neotest cannot successfully complete the call to require("neotest.lib").treesitter.parse_positions and does not find any tests.

Note this issue in CopilotChat which describes how I found this issue: https://github.com/CopilotC-Nvim/CopilotChat.nvim/issues/1099

When calling require("neotest.lib").treesitter.parse_positions, you end up in this code path:

logger.error("Couldn't find positions in path", path, debug.traceback(msg, 2))

I started the debugger and found out that msg is Invalid language name "", using the neotest-golang adapter:

   msg = ...k/.local/share/fredrik/lazy/nvim-nio/lua/nio/control.lua:145: ...m/share/nvim/runtime/lua/vim/treesitter/languagetree.lua:125: Invalid language name ""
       stack traceback:
       	[C]: in function 'assert'
       	...m/share/nvim/runtime/lua/vim/treesitter/languagetree.lua:125: in function 'get_string_parser'
       	...fredrik/lazy/neotest/lua/neotest/lib/treesitter/init.lua:119: in function 'get_parse_root'
       	...fredrik/lazy/neotest/lua/neotest/lib/treesitter/init.lua:160: in function 'parse_positions_from_string'
       	...fredrik/lazy/neotest/lua/neotest/lib/treesitter/init.lua:207: in function 'func'
       	...hare/fredrik/lazy/neotest/lua/neotest/lib/subprocess.lua:156: in function <...hare/fredrik/lazy/neotest/lua/neotest/lib/subprocess.lua:155>
       	[C]: in function 'xpcall'
       	...hare/fredrik/lazy/neotest/lua/neotest/lib/subprocess.lua:155: in function <...hare/fredrik/lazy/neotest/lua/neotest/lib/subprocess.lua:154>
  logger = table: 0x01068a4730
   path = /Users/fredrik/code/public/neotest-golang/tests/go/internal/positions/positions_test.go

Here's a full traceback from the neotest-plenary adapter:

neotest-plenary: ...drik/.local/share/fredrik/lazy/nvim-nio/lua/nio/init.lua:119: The coroutine failed with this message: 
...k/.local/share/fredrik/lazy/nvim-nio/lua/nio/control.lua:145: ...m/share/nvim/runtime/lua/vim/treesitter/languagetree.lua:125: Invalid language name ""
stack traceback:
	[C]: in function 'assert'
	...m/share/nvim/runtime/lua/vim/treesitter/languagetree.lua:125: in function 'get_string_parser'
	...fredrik/lazy/neotest/lua/neotest/lib/treesitter/init.lua:119: in function 'get_parse_root'
	...fredrik/lazy/neotest/lua/neotest/lib/treesitter/init.lua:160: in function 'parse_positions_from_string'
	...fredrik/lazy/neotest/lua/neotest/lib/treesitter/init.lua:207: in function 'func'
	...hare/fredrik/lazy/neotest/lua/neotest/lib/subprocess.lua:156: in function <...hare/fredrik/lazy/neotest/lua/neotest/lib/subprocess.lua:155>
	[C]: in function 'xpcall'
	...hare/fredrik/lazy/neotest/lua/neotest/lib/subprocess.lua:155: in function <...hare/fredrik/lazy/neotest/lua/neotest/lib/subprocess.lua:154>
stack traceback:
	[C]: in function 'error'
	...k/.local/share/fredrik/lazy/nvim-nio/lua/nio/control.lua:145: in function 'call'
	...fredrik/lazy/neotest/lua/neotest/lib/treesitter/init.lua:189: in function 'discover_positions'
	...rik/lazy/neotest-plenary/lua/neotest-plenary/adapter.lua:109: in function 'results'
	...share/fredrik/lazy/neotest/lua/neotest/client/runner.lua:132: in function '_run_spec'
	...share/fredrik/lazy/neotest/lua/neotest/client/runner.lua:89: in function <...share/fredrik/lazy/neotest/lua/neotest/client/runner.lua:88>
stack traceback:
	...l/share/fredrik/lazy/neotest/lua/neotest/client/init.lua:89: in function <...l/share/fredrik/lazy/neotest/lua/neotest/client/init.lua:88>
	[C]: in function 'error'
	...drik/.local/share/fredrik/lazy/nvim-nio/lua/nio/init.lua:119: in function 'gather'
	...share/fredrik/lazy/neotest/lua/neotest/client/runner.lua:94: in function '_run_tree'
	...share/fredrik/lazy/neotest/lua/neotest/client/runner.lua:65: in function <...share/fredrik/lazy/neotest/lua/neotest/client/runner.lua:22>
	[C]: in function 'xpcall'
	...l/share/fredrik/lazy/neotest/lua/neotest/client/init.lua:84: in function 'run_tree'
	...share/fredrik/lazy/neotest/lua/neotest/consumers/run.lua:85: in function 'func'
	...rik/.local/share/fredrik/lazy/nvim-nio/lua/nio/tasks.lua:169: in function <...rik/.local/share/fredrik/lazy/nvim-nio/lua/nio/tasks.lua:168>

To Reproduce

The following will set up the neotest-golang adapter and it won't be able to detect any tests in *.go files, as require("plenary.filetype") was called before Neotest does it (when it detects tests).

vim.opt.runtimepath:remove(vim.fn.expand("~/.config/nvim"))
vim.opt.packpath:remove(vim.fn.expand("~/.local/share/nvim/site"))

local lazypath = "/tmp/lazy/lazy.nvim"

if not vim.loop.fs_stat(lazypath) then
  vim.fn.system({
    "git",
    "clone",
    "--filter=blob:none",
    "https://github.com/folke/lazy.nvim.git",
    "--branch=stable", -- latest stable release
    lazypath,
  })
end

vim.opt.rtp:prepend(lazypath)

require("lazy").setup({
  "nvim-neotest/neotest",
  dependencies = {
    "nvim-lua/plenary.nvim",
    "nvim-treesitter/nvim-treesitter",
    -- Install adapters here
    "fredrikaverpil/neotest-golang",
  },
  config = function()
    -- Trigger bug
    require("plenary.filetype")

    -- Install any required parsers
    require("nvim-treesitter.configs").setup({
      ensure_installed = { "go" },
    })

    require("neotest").setup({
      -- Add adapters to the list
      adapters = { "neotest-golang" },
    })
  end,
})

Here's a sample go test:

// foo_test.go

package main

import "testing"

func Add(a, b int) int {
    return a + b
}

func TestAdd(t *testing.T) {
    result := Add(2, 3)
    if result != 5 {
        t.Errorf("Expected 5, but got %d", result)
    }
}

Steps to reproduce the behavior:

  1. Launch Neovim with the minimal.lua: nvim --clean -u minimal.lua
  2. Open the Go test file.
  3. Open the test summary panel.
  4. Notice how no tests are shown for the Go file.

Now comment out require("plenary.filetype") from minimal.lua and try again. The test is shown.

Expected behavior

The test should show regardless of whether require("plenary.filetype") was called prior to Neotest doing it or not.

Logs

N/A

Additional context

If you make sure that Neotest calls require("plenary.filetype") before e.g. CopilotChat does, both plugins works as expected.

It's possible that this is a plenary bug?

fredrikaverpil avatar May 01 '25 16:05 fredrikaverpil

@fredrikaverpil It's happening to me too. I dig into it myself and I'm erroring out on neotest.Client:get_nearest: no nodes are found, the range is always nil. Is this what you experience? You talk here about plenary. I don't know if it's related. Do you have a fix?

ruicsh avatar Jun 14 '25 21:06 ruicsh

@ruicsh Not sure without more information. Share the full stack trace? You get the same error in the crash as mentioned above?

I solved it on my end by changing up when Neotest (with its require("plenary.filetype")) is loaded, as mentioned above.

fredrikaverpil avatar Jun 15 '25 16:06 fredrikaverpil

hey @fredrikaverpil thanks for your response. Mine doesn't crash, it just prints out "No tests found" and doesn't run any tests. But, it's also because of 'copilot-chat' plugin. If I disable it, 'neotest' works fine. You mentioned you were able to fix it by making sure neotest gets loaded before copilot-chat? How did you do that, with lazy events?

ruicsh avatar Jun 15 '25 21:06 ruicsh

Hopefully this helps (just a workaround): https://github.com/CopilotC-Nvim/CopilotChat.nvim/pull/1162

fredrikaverpil avatar Jun 17 '25 05:06 fredrikaverpil

hey @fredrikaverpil yes it helped, made neotest work. But, I ended up using vim-test. I prefer to have the output panel open a full height vertical split and I couldn't really do it with neotest and it was really easy with vim-test. But thanks for your time. :)

ruicsh avatar Jun 17 '25 17:06 ruicsh

hey @fredrikaverpil thanks for your response. Mine doesn't crash, it just prints out "No tests found" and doesn't run any tests. But, it's also because of 'copilot-chat' plugin. If I disable it, 'neotest' works fine. You mentioned you were able to fix it by making sure neotest gets loaded before copilot-chat? How did you do that, with lazy events?

Mine was also not crashing but I finally found the issue. As nothing was working I searched for alternatives and nvim-test gave me the final clue, at least for me, when I got a message complaining about no treesitter parser for ruby present.

So the solution was installing the parser, in my case with TSInstall ruby, then neotest is already working as always.

In README section for writing adapters it mentions the use of treesitter to parse the tests, but maybe it's worth to add a warning to run checkhealth to check for missing language parsers when "tests not found" error is shown.

This plugin is a must in my neovim config, I hope this helps others too.

ialiendeg avatar Jun 20 '25 07:06 ialiendeg

I've got something bizarre happening. I share the same config across my macOS laptop and my Arch desktop.

I have the issue where no tests are found (any adapter) on my Arch machine, but works flawlessly on my macOS.

hahuang65 avatar Nov 04 '25 17:11 hahuang65

I've found my solution to why my Golang tests aren't being found:

{ "fredrikaverpil/neotest-golang", commit = "cac1039" }, -- Pin to before statement_list change

Essentially, the neotest-golang is using a newer feature that's available in nvim-treesitter 0.11.0 and I was on 0.10.0

● Looking at the debugging we did, here's why we
  pinned to commit cac1039:

  The Problem

  TreeSitter Node Type Mismatch

  When we enabled debug logging and read the neotest
   log file at ~/.local/state/nvim/neotest.log, we
  found this critical error:

  Query error at 75:4. Invalid node type
  "statement_list"

  This meant:
  - neotest-golang (newer versions) uses TreeSitter
  queries that reference a statement_list node type
  - Your nvim-treesitter Go parser (v0.10.0) uses
  the older block node type instead
  - When neotest-golang tried to parse your Go test
  files, the TreeSitter query failed because
  statement_list didn't exist in your parser

  Why Commit cac1039?

  This specific commit represents the last version
  of neotest-golang before the statement_list node
  type was introduced. By pinning to it:

  1. The plugin uses TreeSitter queries with block
  (which your parser understands)
  2. Test detection works correctly
  3. You avoid the query parsing error

  Why Not Update TreeSitter Instead?

  We tried updating nvim-treesitter, but it was
  already at the latest version available in your
  setup. The newer Go parser grammar that includes
  statement_list wasn't available yet in your
  nvim-treesitter version.

  The Trade-off

  Pinning to cac1039 means you're using a slightly
  older version of neotest-golang, but it's the
  pragmatic solution that makes everything work with
   your current TreeSitter setup. When you
  eventually update nvim-treesitter to a version
  with the newer Go parser, you can remove the
  commit pin and use the latest neotest-golang.

hahuang65 avatar Nov 04 '25 19:11 hahuang65

@hahuang65 your issue is unrelated to the plenary.filetype issue I originally reported here.

fredrikaverpil avatar Nov 04 '25 19:11 fredrikaverpil

@hahuang65 your issue is unrelated to the plenary.filetype issue I originally reported here.

Yeah, I'm sorry. I got confused and thought I was posting the message in #495

hahuang65 avatar Nov 04 '25 19:11 hahuang65