Skip to content

Commit

Permalink
feat: mkdocs
Browse files Browse the repository at this point in the history
  • Loading branch information
fredrikaverpil committed Jan 19, 2025
1 parent 9c277d5 commit e3049ef
Show file tree
Hide file tree
Showing 12 changed files with 1,512 additions and 875 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
.tests
site
1 change: 1 addition & 0 deletions .pkgx.yml
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
dependencies:
- go.dev
- python
879 changes: 4 additions & 875 deletions README.md

Large diffs are not rendered by default.

238 changes: 238 additions & 0 deletions docs/config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
---
icon: material/cog
---

# Configuration

## Options

!!! tip "Recipes"

See [the recipes](recipes.md) for usage examples of the below options.

### `runner`

Default value: `"go"`

This option defines the test execution runner, which by default is set to `"go"`
and will use `go test` to write test output to stdout.

!!! warning "Windows, Ubuntu Snaps"

If you are on Windows or using Ubuntu snaps, you might want to set the runner
to `"gotestsum"` and/or enable the [`sanitize_output`](#sanitize_output) option. See
[this issue comment](https://github.com/fredrikaverpil/neotest-golang/issues/193#issuecomment-2362845806)
for more details and continue reading.

To improve reliability, you can choose to set
[`gotestsum`](https://github.com/gotestyourself/gotestsum) as the test runner.
This tool allows the adapter to write test command output directly to a JSON
file without having to go through stdout.

Using `gotestsum` offers the following benefits:

- On certain platforms (such as Windows) or in certain terminals, there's a risk
of ANSI codes or other characters being seemingly randomly inserted into the
JSON test output. This can corrupt the data and cause problems with test
output JSON decoding. Enabling `gotestsum` eliminates these issues, as the
test output is then written directly to file.
- When you "attach" (in the Neotest summary window) to a running test, you'll
see clean `go test` output instead of having to navigate through
difficult-to-read JSON, as `gotestsum` is configured to _also_ output non-JSON
test execution to stdout.

Gotestsum calls `go test` behind the scenes, so your `go_test_args`
configuration remains valid and will still apply.

??? example "Configure neotest-golang to use `gotestsum` as test runner"

Make the `gotestsum` command available via e.g.
[mason.nvim](https://github.com/williamboman/mason.nvim) or by running the
following in your shell:

```bash
go install gotest.tools/gotestsum@latest
```

Then add the required configuration:

```lua
local config = { -- Specify configuration
runner = "gotestsum"
}
require("neotest").setup({
adapters = {
require("neotest-golang")(config), -- Apply configuration
},
})
```

### `go_test_args`

Default value: `{ "-v", "-race", "-count=1" }`

Arguments to pass into `go test`. See `go help test`, `go help testflag`,
`go help build` for possible arguments.

The `-json` flag is mandatory and is always appended to `go test` automatically.

The value can also be passed in as a function.

!!! warning "CGO"

The `-race` flag (in `go_test_args`) requires CGO to be enabled
(`CGO_ENABLED=1` is the default) and a C compiler (such as GCC) to be
installed. However, since Go 1.20, this is not a requirement on macOS. I have
included the `-race` argument as default, as it provides good production
defaults. See [this issue](https://github.com/golang/go/issues/9918) for more
details.

### `gotestsum_args`

Default value: `{ "--format=standard-verbose" }`

Arguments to pass into `gotestsum`. Will only be applicable if
`runner = "gotestsum"`.

The value can also be passed in as a function.

### `go_list_args`

Default value: `{}`

Arguments to pass into `go list`. The main purpose of `go list` is to internally
translate between filepaths and Go package import paths.

A mandatory query is passed into the `-f` flag and is always appended
automatically, so that the necessary fields can be extracted.

The value can also be passed in as a function.

### `dap_mode`

Default value: `"dap-go"`

This option toggles between relying on
[leoluz/nvim-dap-go](https://github.com/leoluz/nvim-dap-go) so supply the delve
DAP configuration, or whether you wish to bring your own DAP configuration.

Set to `"manual"` for manual configuration.

The value can also be passed in as a function.

### `dap_go_opts`

Default value: `{}`

If using `dap_mode = "dap-go"`, you can supply dap-go with custom options.

The value can also be passed in as a function.

### `dap_manual_config`

Default value: `{}`

The configuration to apply if `dap_mode == "manual"`.

The value can also be passed in as a function.

### `testify_enabled`

Default value: `false`

Enable support for [testify](https://github.com/stretchr/testify) suites.

!!! warning "Not enabled by default"

This feature comes with some caveats and nuances, which is why it is not enabled
by default. I advise you to only enable this if you need it.

There are some real shenaningans going on behind the scenes to make this work.
😅 First, an in-memory lookup of "receiver type-to-suite test function" will be
created of all Go test files in your project. Then, the generated Neotest node
tree is modified by mutating private attributes and merging of nodes to avoid
duplicates. I'm personally a bit afraid of the maintenance burden of this
feature... 🙈

!!! note "Subtests not supported"

Right now, nested tests and table tests are not supported. All of this can be
remedied at any time by extending the treesitter queries. Feel free to dig in
and open a PR!

### `colorize_test_output`

Default value: `true`

Enable output color for `SUCCESS`, `FAIL`, and `SKIP` tests.

### `warn_test_name_dupes`

Default value: `true`

Warn about duplicate test names within the same Go package.

### `warn_test_not_executed`

Default value: `true`

Warn if test was not executed.

### `log_level`

Default value: `"vim.log.levels.WARN"`

The `neotest-golang.log` log-level.

### `sanitize_output`

Default value: `false`

Filter control characters and non-printable characters from test output.
Requires the [uga-rosa/utf8.nvim](https://github.com/uga-rosa/utf8.nvim)
library.

When tests write non-printable characters to stdout/stderr, they can cause
various issues like failing to write output to disk or UI rendering problems.
The `sanitize_output` option helps clean up such output by preserving UTF-8 and
replacing control characters with the Unicode replacement character (�).

This is particularly useful when:

- Tests write bytes to stdout/stderr.
- Test output contains terminal control sequences.
- Test output includes non-printable characters.

The sanitization preserves all regular printable characters including tabs,
newlines, and carriage returns.

??? example "Example config"

```diff
return {
{
"nvim-neotest/neotest",
dependencies = {
"nvim-neotest/nvim-nio",
"nvim-lua/plenary.nvim",
"antoinemadec/FixCursorHold.nvim",
"nvim-treesitter/nvim-treesitter",
- "fredrikaverpil/neotest-golang", -- Installation
+ {
+ "fredrikaverpil/neotest-golang", -- Installation
+ dependencies = {
+ "uga-rosa/utf8.nvim", -- Additional dependency required
+ },
+ },
},
config = function()
require("neotest").setup({
adapters = {
- require("neotest-golang"), -- Registration
+ require("neotest-golang")({ sanitize_output = true }), -- Registration
},
})
end,
},
}
```
111 changes: 111 additions & 0 deletions docs/contrib.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
---
icon: material/heart-multiple-outline
---

# 🙏 PRs are welcome

Improvement suggestion PRs to this repo are very much welcome, and I encourage
you to begin by reading the below paragraph on the adapter design and engage in
the [discussions](https://github.com/fredrikaverpil/neotest-golang/discussions)
in case the change is not trivial.

You can run tests, formatting and linting locally with `make all`. Install
dependencies with `make install`. Have a look at the `Makefile` for more
details. You can also use the neotest-plenary and neotest-golang adapters to run
the tests of this repo within Neovim.

### AST and tree-sitter

To figure out new tree-sitter queries (for detecting tests), the following
commands are available in Neovim to aid you:

- `:Inspect` to show the highlight groups under the cursor.
- `:InspectTree` to show the parsed syntax tree (formerly known as
"TSPlayground").
- `:EditQuery` to open the Live Query Editor (Nvim 0.10+).

For example, open up a Go test file and then execute `:InspectTree`. A new
window will appear which shows what the tree-sitter query syntax representation
looks like for the Go test file.

Again, from the Go test file, execute `:EditQuery` to open up the query editor
in a separate window. In the editor, you can now start creating your syntax
query and play around. You can paste in queries from
[`query.lua`](https://github.com/fredrikaverpil/neotest-golang/blob/main/lua/neotest-golang/query.lua)
in the editor, to see how the query behaves and highlights parts of your Go test
file.

## General design of the adapter

### Treesitter queries detect tests

Neotest leverages treesitter AST-parsing of source code to detect tests. This
adapter supplies queries so to figure out what is considered a test.

From the result of these queries, a Neotest "position" tree is built (can be
visualized through the "Neotest summary"). Each position in the tree represents
either a `dir`, `file` or `test` type. Neotest also has a notion of a
`namespace` position type, but this is ignored by default by this adapter (but
leveraged to supply testify support).

### Generating valid `go test` commands

The `dir`, `file` and `test` tree position types cannot be directly translated
over to Go so to produce a valid `go test` command. Go primarily cares about a
Go package's import path, test name regexp filters and the current working
directory.

For example, these are all valid `go test` command:

```bash
# run all tests, recursing sub-packages, in the current working directory.
go test ./...

# run all tests in a given package 'x', by specifying the full import path
go test github.com/fredrikaverpil/neotest-golang/x

# run all tests in a given package 'x', recursing sub-packages
go test github.com/fredrikaverpil/neotest-golang/x/...

# run _some_ tests in a given package, based on a regexp filter
go test github.com/fredrikaverpil/neotest-golang -run "^(^TestFoo$|^TestBar$)$"
```

> [!NOTE]
>
> All the above commands must be run somewhere beneath the location of the
> `go.mod` file specifying the _module_ name, which in this example is
> `github.com/fredrikaverpil/neotest-golang`.
I figured out that by executing `go list -json ./...` in the `go.mod` root
location, the output provides valuable information about test files/folders and
their corresponding Go package's import path. This data is key to being able to
take the Neotest/treesitter position type and generate a valid `go test` command
for it. In essence, this approach is what makes neotest-golang so robust.

### Output processing

Neotest captures the stdout from the test execution command and writes it to
disk as a temporary file. The adapter is responsible for reading the file(s) and
reporting back status and output to the Neotest tree (and specifically the
position in the tree which was executed). It is therefore crucial for outputting
structured data, which in this case is done with `go test -json`.

One challenge here is that Go build errors are not part of the strucutured JSON
output (although captured in the stdout) and needs to be looked for in other
ways.

Another challenge is to properly populate statuses and errors into the
corresponding Neotest tree position. This becomes increasingly difficult when
you consider running tests in a recursive manner (e.g. `go test -json ./...`).

Errors are recorded and populated, per position type, along with its
corresponding buffer's line number. Neotest can then show the errors inline as
diagnostics.

I've taken an approach with this adapter where I record test outcome for each
Neotest position type and populate it onto each of them, when applicable.

On some systems and terminals, there are great issues with the `go test` output.
I've therefore made it possible to make the adapter rely on output saved
directly to disk without going through stdout, by leveraging `gotestsum`.
33 changes: 33 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
icon: material/information
---

--8<-- "README.md"

---

??? question "Why a second Neotest adapter for Go? 🤔"

While using [neotest-go](https://github.com/nvim-neotest/neotest-go) I stumbled
upon many problems which seemed difficult to solve in that codebase.

I have full respect for the time and efforts put in by the developer(s) of
neotest-go. I do not aim in any way to diminish their needs or efforts. However,
I wanted to see if I could fix these issues by diving into the 🕳️🐇 of Neotest
and building my own adapter. Below is a list of neotest-go issues which are not
present in neotest-golang (this project):

| Neotest-go issue | URL |
| ------------------------------------------------------- | --------------------------------------------------------------------- |
| Support for Testify framework | [neotest-go#6](https://github.com/nvim-neotest/neotest-go/issues/6) |
| DAP support | [neotest-go#12](https://github.com/nvim-neotest/neotest-go/issues/12) |
| Test Output in JSON, making it difficult to read | [neotest-go#52](https://github.com/nvim-neotest/neotest-go/issues/52) |
| Support for Nested Subtests | [neotest-go#74](https://github.com/nvim-neotest/neotest-go/issues/74) |
| Diagnostics for table tests on the line of failure | [neotest-go#75](https://github.com/nvim-neotest/neotest-go/issues/75) |
| "Run nearest" runs all tests | [neotest-go#83](https://github.com/nvim-neotest/neotest-go/issues/83) |
| Table tests not recognized when defined inside for-loop | [neotest-go#86](https://github.com/nvim-neotest/neotest-go/issues/86) |
| Running test suite doesn't work | [neotest-go#89](https://github.com/nvim-neotest/neotest-go/issues/89) |

A comparison in number of GitHub stars between the projects:

[![Star History Chart](https://api.star-history.com/svg?repos=fredrikaverpil/neotest-golang,nvim-neotest/neotest-go&type=Date)](https://star-history.com/#fredrikaverpil/neotest-golang&nvim-neotest/neotest-go&Date)
Loading

0 comments on commit e3049ef

Please sign in to comment.