nvim-neotest / neotest-python

MIT License
115 stars 34 forks source link

Run decorated test when cursor is on the decorators #31

Closed OddBloke closed 1 year ago

OddBloke commented 1 year ago

Currently, with a test file that looks like:

def test_one():
    pass

@pytest.mark.parametrize(...)
def test_thing(...):
   pass

invoking neotest.run.run with the cursor on the parametrize line results in test_one being run.

I would prefer for test_thing to be run: that's the test whose definition I'm editing.

OddBloke commented 1 year ago

I've never touched treesitter queries before, but my first blind guess for functions is a decent approximation:

--- a/lua/neotest-python/init.lua
+++ b/lua/neotest-python/init.lua
@@ -91,6 +91,12 @@ function PythonNeotestAdapter.discover_positions(path)
     (class_definition
      name: (identifier) @namespace.name)
      @namespace.definition
+
+    (decorated_definition
+      ((function_definition
+        name: (identifier) @test.name)
+        (#match? @test.name "^test")))
+        @test.definition
   ]]
   local root = PythonNeotestAdapter.root(path)
   local python = get_python(root)

This annotates the first decorator line, rather than the def line. I tried doing the same copy/paste trick with the class definition and that didn't work.

rcarriga commented 1 year ago

Actually have been meaning to add support for parsing the parameterized tests as well, just haven't had a chance.

I put together a PR for neotest-dotnet that did something very similar to what's needed here https://github.com/Issafalcon/neotest-dotnet/pull/20. The core of the change is discussed here https://github.com/nvim-neotest/neotest/discussions/24#discussioncomment-3741387 where the parsing is customised to run queries after the initial parse, so the initial queries remain the same and then we traverse the tree to check if there are parameters.

If you want to have a go at it, happy to help but if not, I'll get around to it myself at some stage :smile:

OddBloke commented 1 year ago

This is actually a more general problem than just parametrized tests: @mock.patch decorators, for example, are included in the prior test's definition. Doing more with test parameterization would certainly be cool though!

I figured out my classes problem: namespaces nest, and my first copy/paste rule meant that two namespaces were being annotated for decorated classes: the definition itself and the decorated definition, with the former nesting inside the latter. I've pushed up #34 which has a proper approach to this.