fredrikaverpil / neotest-golang

Reliable Neotest adapter for running Go tests in Neovim.
MIT License
129 stars 17 forks source link

feature: support table tests for test case structs with no fields #155

Open jstensland opened 3 months ago

jstensland commented 3 months ago

Did you check docs and existing issues?

Is your feature request related to a problem? Please describe.

I have multiple packages with test cases where there's an anonymous struct of test cases and the cases do not include fields. The current support for table tests do not detect these. e.g.

func TestTableTestInlineStructLoopNotKeyed(t *testing.T) {
    for _, tc := range []struct {
        name     string
        x        int
        y        int
        expected int
    }{
        {"TableTest1", 1, 2, 3}, // no `name:` to match on
        {"TableTest2", 3, 4, 7},
    } {
        t.Run(tc.name, func(t *testing.T) {
            if Add(tc.x, tc.y) != tc.expected {
                t.Fail()
            }
        })
    }
}

Given the support for this functionality when the field is there, it would be nice to support this form as well.

Describe the solution you'd like to see.

I would like to be able to run the nearest test case when my cursor is on it, or to run a single test case from the summary

Describe alternatives you've considered.

The obvious alternative is to just run the full test, which does work.

Additional context

I tried updated the treesitter query for these. I could only get as far as matchings the struct def with the first argument to run in this form (similar to what exists) but wasn't sure if it's possible to ask treesitter for the index of the sibling in the list of declared field, such that I could identify that name field to capture the test name. It may be good enough to assume its first, given this is just matching a specific code pattern anyways

fredrikaverpil commented 3 months ago

We should be able to support this by extending the current treesitter queries: https://github.com/fredrikaverpil/neotest-golang/blob/main/lua/neotest-golang/query.lua

If you want to take a stab at it, there are Go tests in positions_test.go (in which you would add the test you provided above) as well as a lua test file that asserts that the tests are detected by the neotest-golang adapter in positions_spec.lua. There are instructions in the README on how to play around with the treesitter queries in query.lua as well as how to run the lua tests with the Makefile.

fredrikaverpil commented 3 months ago

Sorry, I somehow missed you already looked into this. 😅

I could only get as far as matchings the struct def with the first argument to run in this form (similar to what exists) but wasn't sure if it's possible to ask treesitter for the index of the sibling in the list of declared field, such that I could identify that name field to capture the test name.

I see what you mean. Not sure myself without digging (not at my machine until next week).

jstensland commented 3 months ago

Seems possible to just match the first string defined in the struct which is likely the right one. Seems like an option if there's not a better way to index the fields between struct definition and literal definitions

fredrikaverpil commented 3 months ago

Please give https://github.com/fredrikaverpil/neotest-golang/pull/156 a try?

Load the plugin by setting branch = "table-test-without-struct-fields" in the lazy plugin specs.

Seems possible to just match the first string defined in the struct which is likely the right one.

This is exactly what I did now.

jstensland commented 2 months ago

Sorry for the long delay. Two things

  1. To match other test case detection, how about able also supporting the variation where the struct is defined outside of the for loop? Those are not currently detected. Adjusting my original example, that's something like

    func TestTableTestInlineStructLoopNotKeyed(t *testing.T) {
     testcases := []struct {
        name     string
        x        int
        y        int
        expected int
    }{
        {"TableTest1", 1, 2, 3}, // no `name:` to match on
        {"TableTest2", 3, 4, 7},
    } 
    for _, tc := testcases {
        t.Run(tc.name, func(t *testing.T) {
            if Add(tc.x, tc.y) != tc.expected {
                t.Fail()
            }
        })
    }
    }
  2. I am getting the following error running one of the tests cases

    Test(s) not associated (not found/executed):  { '/path/to/file_test.go::TestName::"casename"::"secondstringfield"' }
fredrikaverpil commented 2 months ago

Sorry for the silence here. I'm quite busy at work and with life at the moment. I'll have a look when I have the time. Feel free to take a stab at it in case you wish.

fredrikaverpil commented 2 months ago

@jstensland I updated the query in #156 Please give this a try and let me know how this works for you:

{
  "fredrikaverpil/neotest-golang",
  branch = "table-test-without-struct-fields",
}