mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-09-10 07:36:27 -04:00
Restructure the just recipes for running integration tests (#5720)
`just e2e` used to be the *visible-UI* test runner. Running it with no arguments launched every integration test in a visible UI — painfully slow — and it was easy to type `just e2e` out of habit when you actually meant `just e2e-all` (the headless run-all). This PR reshuffles the recipes so the common, fast path is the one with the shortest name. ## Recipe changes | Command | Before | After | | --- | --- | --- | | `just e2e` | All tests, **visible UI** (very slow) | All tests, **headless** (what CI runs) | | `just e2e <name>` | — (no such target) | That one test, **headless** | | `just e2e-cli [--slow\|--sandbox\|--debug] <name>` | — | A test in a **visible UI** (the old `e2e`) | | `just e2e-tui` | unchanged | unchanged | | `just e2e-all` | All tests, headless | **removed** (now redundant) | `just e2e` and `just e2e-cli` accept either a test name (`submodule/reset`) or a full file path (`pkg/integration/tests/submodule/reset.go`), and `e2e-cli`/`e2e-tui` mirror the two `cmd/integration_test/main.go` subcommands (`cli` and `tui`). Also added zsh tab-completion for the test names, so `just e2e sub<Tab>` expands to `just e2e submodule/`, then drills into the tests within.
This commit is contained in:
commit
f103cf26dd
14
.vscode/tasks.json
vendored
14
.vscode/tasks.json
vendored
|
|
@ -24,7 +24,7 @@
|
|||
{
|
||||
"label": "Run current file integration test",
|
||||
"type": "shell",
|
||||
"command": "go run cmd/integration_test/main.go cli ${relativeFile}",
|
||||
"command": "just e2e ${relativeFile}",
|
||||
"problemMatcher": [],
|
||||
"group": {
|
||||
"kind": "test",
|
||||
|
|
@ -61,18 +61,6 @@
|
|||
"focus": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Open deprecated test TUI",
|
||||
"type": "shell",
|
||||
"command": "go run pkg/integration/deprecated/cmd/tui/main.go",
|
||||
"problemMatcher": [],
|
||||
"group": {
|
||||
"kind": "test",
|
||||
},
|
||||
"presentation": {
|
||||
"focus": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Sync tests list",
|
||||
"type": "shell",
|
||||
|
|
|
|||
|
|
@ -21,8 +21,9 @@ Windows box has only `just`).
|
|||
- `just format` — `gofumpt -l -w .`. Run before every commit.
|
||||
- `just build` — build the binary.
|
||||
- `just unit-test` — `go test ./... -short`.
|
||||
- `just e2e-all` — run all integration tests headlessly (`just e2e <name>` runs a
|
||||
single one with a visible UI).
|
||||
- `just e2e` — run all integration tests headlessly; `just e2e <name>` runs a
|
||||
single one headlessly too. `just e2e-cli <name>` runs one with a visible UI
|
||||
(most useful with `--sandbox` or `--slow`).
|
||||
- `just lint` — run golangci-lint.
|
||||
|
||||
## When to commit
|
||||
|
|
@ -45,7 +46,7 @@ while still being meaningful and self-contained.
|
|||
|
||||
- **Every commit must compile and pass all tests.** No "WIP" commits, no
|
||||
commits that leave the tree broken and rely on a follow-up to fix it.
|
||||
- **Every commit must be `gofumpt`-formatted.** Run `make format` before
|
||||
- **Every commit must be `gofumpt`-formatted.** Run `just format` before
|
||||
committing.
|
||||
- **Commit messages explain _why_, not _what_.** The diff already shows what
|
||||
changed; the message should capture the motivation, the constraint, or the
|
||||
|
|
@ -283,7 +284,7 @@ So:
|
|||
- For changes to `userConfig` fields specifically, don't edit
|
||||
`docs-master/Config.md` by hand either — the relevant section is
|
||||
auto-generated from the struct field doc comments. After editing the
|
||||
struct, run `make generate` and include the regenerated
|
||||
struct, run `just generate` and include the regenerated
|
||||
`docs-master/Config.md` (and `schema-master/config.json`) in your commit.
|
||||
- Don't hard-wrap the doc comments on `userConfig` fields. This applies
|
||||
*only* to `userConfig`, because those comments are fed through the doc
|
||||
|
|
|
|||
23
justfile
23
justfile
|
|
@ -23,7 +23,7 @@ unit-test:
|
|||
|
||||
# Run both unit tests and integration tests.
|
||||
[unix]
|
||||
test: unit-test e2e-all
|
||||
test: unit-test e2e
|
||||
|
||||
# On Windows, integration tests are not supported right now
|
||||
[windows]
|
||||
|
|
@ -39,18 +39,29 @@ format:
|
|||
lint:
|
||||
./scripts/golangci-lint-shim.sh run
|
||||
|
||||
# Run integration tests with a visible UI. Most useful for running a single test; for running all tests, use `e2e-all` instead.
|
||||
e2e-test-command := "go test pkg/integration/clients/*.go"
|
||||
|
||||
# Run integration tests headlessly: no args runs all tests, a test name (or path) runs just that one. Use e2e-cli for a visible UI.
|
||||
e2e *args:
|
||||
{{ if args == "" { e2e-test-command } else { \
|
||||
e2e-test-command + " -run 'TestIntegration/" + \
|
||||
replace( \
|
||||
replace_regex( \
|
||||
replace_regex(args, '\S*pkg/integration/tests/', ''), \
|
||||
'\.go( |$)', '${1}' \
|
||||
), \
|
||||
" ", "$' && " + e2e-test-command + " -run 'TestIntegration/" \
|
||||
) + "$'" \
|
||||
} }}
|
||||
|
||||
# Run a single integration test with a visible UI; most useful with --sandbox or --slow.
|
||||
e2e-cli *args:
|
||||
go run cmd/integration_test/main.go cli {{ args }}
|
||||
|
||||
# Open the TUI for running integration tests.
|
||||
e2e-tui *args:
|
||||
go run cmd/integration_test/main.go tui {{ args }}
|
||||
|
||||
# Run all integration tests headlessly (without a visible UI).
|
||||
e2e-all:
|
||||
go test pkg/integration/clients/*.go
|
||||
|
||||
# Run some tests on the current commit, similar to what CI does.
|
||||
check:
|
||||
./scripts/check_commit.sh
|
||||
|
|
|
|||
|
|
@ -2,21 +2,21 @@
|
|||
|
||||
The pkg/integration package is for integration testing: that is, actually running a real lazygit session and having a robot pretend to be a human user and then making assertions that everything works as expected.
|
||||
|
||||
TL;DR: integration tests live in pkg/integration/tests. Run integration tests with:
|
||||
TL;DR: integration tests live in pkg/integration/tests, and we run them through the [`just`](https://github.com/casey/just) recipes in the repo's `justfile`. Run the whole suite headlessly with:
|
||||
|
||||
```sh
|
||||
go run cmd/integration_test/main.go tui
|
||||
just e2e
|
||||
```
|
||||
|
||||
or
|
||||
or open a terminal UI to browse and run individual tests with:
|
||||
|
||||
```sh
|
||||
go run cmd/integration_test/main.go cli [--slow or --sandbox] [testname or testpath...]
|
||||
just e2e-tui
|
||||
```
|
||||
|
||||
## Writing tests
|
||||
|
||||
The tests live in pkg/integration/tests. Each test is registered in `pkg/integration/tests/test_list.go` which is an auto-generated file. You can re-generate that file by running `go generate ./...` at the root of the Lazygit repo.
|
||||
The tests live in pkg/integration/tests. Each test is registered in `pkg/integration/tests/test_list.go` which is an auto-generated file. You can re-generate that file by running `just generate` at the root of the Lazygit repo.
|
||||
|
||||
Each test has two important steps: the setup step and the run step.
|
||||
|
||||
|
|
@ -38,19 +38,18 @@ The run step has two arguments passed in:
|
|||
|
||||
## Running tests
|
||||
|
||||
There are three ways to invoke a test:
|
||||
We drive the integration tests through the [`just`](https://github.com/casey/just) recipes in the repo's `justfile`, so you'll want `just` installed to run them as described here. (The recipes are thin wrappers, so if you can't install `just`, the underlying commands are right there in the `justfile`.)
|
||||
|
||||
1. go run cmd/integration_test/main.go cli [--slow or --sandbox] [testname or testpath...]
|
||||
2. go run cmd/integration_test/main.go tui
|
||||
3. go test pkg/integration/clients/*.go
|
||||
- `just e2e` — run the whole suite headlessly, with no visible UI. This is what CI does, and the fastest way to run everything.
|
||||
- `just e2e <name>` — run a single test headlessly, e.g. `just e2e commit/new_branch`; the fastest way to run one test. You can pass several names at once, or a full file path like `pkg/integration/tests/commit/new_branch.go`.
|
||||
- `just e2e-cli [--slow|--sandbox|--debug] <name>` — run a single test in a *visible* lazygit UI, so you can watch it (see slow mode below, and sandbox mode and debugging in the following sections).
|
||||
- `just e2e-tui` — open a terminal UI for browsing and running tests; the easiest way to find and run a test without having to type its name.
|
||||
|
||||
The first, the test runner, is for directly running a test from the command line. If you pass no arguments, it runs all tests.
|
||||
The second, the TUI, is for running tests from a terminal UI where it's easier to find a test and run it without having to copy it's name and paste it into the terminal. This is the easiest approach by far.
|
||||
The third, the go-test command, intended only for use in CI, to be run along with the other `go test` tests. This runs the tests in headless mode so there's no visual output.
|
||||
The name of a test is based on its path, so the name of the test at `pkg/integration/tests/commit/new_branch.go` is `commit/new_branch`.
|
||||
|
||||
The name of a test is based on its path, so the name of the test at `pkg/integration/tests/commit/new_branch.go` is commit/new_branch. So to run it with our test runner you would run `go run cmd/integration_test/main.go cli commit/new_branch`.
|
||||
zsh users can get tab-completion of these test names — `just e2e sub<Tab>` expands to `submodule/…` — by sourcing `scripts/just_e2e_completion.zsh` from their `.zshrc`; see the comment at the top of that file for details.
|
||||
|
||||
You can pass the INPUT_DELAY env var to the test runner in order to set a delay in milliseconds between keypresses or mouse clicks, which helps for watching a test at a realistic speed to understand what it's doing. Or you can pass the '--slow' flag which sets a pre-set 'slow' key delay. In the tui you can press 't' to run the test in slow mode.
|
||||
To watch a test run at a realistic speed, pass `--slow` to `just e2e-cli`; it sets a pre-set delay between keypresses and mouse clicks. For finer control, set the `INPUT_DELAY` env var to a number of milliseconds instead, e.g. `INPUT_DELAY=200 just e2e-cli commit/new_branch`. In the TUI you can press 't' to run a test in slow mode.
|
||||
|
||||
The resultant repo will be stored in `test/_results`, so if you're not sure what went wrong you can go there and inspect the repo.
|
||||
|
||||
|
|
@ -67,8 +66,8 @@ The test will run in a VSCode terminal:
|
|||
|
||||
Debugging an integration test is possible in two ways:
|
||||
|
||||
1. Use the -debug option of the integration test runner's "cli" command, e.g. `go run cmd/integration_test/main.go cli -debug tag/reset.go`
|
||||
2. Select a test in the "tui" runner and hit "d" to debug it.
|
||||
1. Pass `--debug` to `just e2e-cli`, e.g. `just e2e-cli --debug tag/reset`.
|
||||
2. Select a test in `just e2e-tui` and hit "d" to debug it.
|
||||
|
||||
In both cases the test runner will print to the console that it is waiting for a debugger to attach, so now you need to tell your debugger to attach to a running process with the name "test_lazygit". If you are using Visual Studio Code, an easy way to do that is to use the "Attach to integration test runner" debug configuration. The test runner will resume automatically when it detects that a debugger was attached. Don't forget to set a breakpoint in the code that you want to step through, otherwise the test will just finish (i.e. it doesn't stop in the debugger automatically).
|
||||
|
||||
|
|
@ -76,7 +75,7 @@ In both cases the test runner will print to the console that it is waiting for a
|
|||
|
||||
Say you want to do a manual test of how lazygit handles merge-conflicts, but you can't be bothered actually finding a way to create merge conflicts in a repo. To make your life easier, you can simply run a merge-conflicts test in sandbox mode, meaning the setup step is run for you, and then instead of the test driving the lazygit session, you're allowed to drive it yourself.
|
||||
|
||||
To run a test in sandbox mode you can press 's' on a test in the test TUI or in the test runner pass the --sandbox argument.
|
||||
To run a test in sandbox mode, press 's' on a test in `just e2e-tui`, or pass `--sandbox` to `just e2e-cli`, e.g. `just e2e-cli --sandbox conflicts/resolve_multiple_files`.
|
||||
|
||||
## Tips for writing tests
|
||||
|
||||
|
|
|
|||
56
scripts/just_e2e_completion.zsh
Normal file
56
scripts/just_e2e_completion.zsh
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
# Zsh completion for the `e2e` and `e2e-cli` recipes in lazygit's justfile.
|
||||
#
|
||||
# These recipes take integration-test names (e.g. submodule/reset). This makes
|
||||
# `just e2e <Tab>` complete them from pkg/integration/tests/. To enable it, add
|
||||
# the following to your ~/.zshrc, *after* the line that runs `compinit`:
|
||||
#
|
||||
# source /path/to/lazygit/scripts/just_e2e_completion.zsh
|
||||
#
|
||||
# It is a no-op when `just` isn't installed, and only kicks in inside a project
|
||||
# that has a justfile and a pkg/integration/tests/ directory, so it is harmless
|
||||
# to source unconditionally.
|
||||
|
||||
(( $+commands[just] )) || return 0
|
||||
|
||||
# just's own completion is clap-dynamic and has no hook for completing a
|
||||
# recipe's arguments, so we wrap it: handle the e2e recipes ourselves and
|
||||
# delegate everything else (recipe names, flags, ...) to just's completer.
|
||||
source <(JUST_COMPLETE=zsh just) # defines _clap_dynamic_completer_just
|
||||
|
||||
_just_lazygit_e2e() {
|
||||
if (( CURRENT > 2 )); then
|
||||
case ${words[2]} in
|
||||
e2e | e2e-cli)
|
||||
# Find the justfile's directory, then complete the integration
|
||||
# tests under pkg/integration/tests/ relative to it.
|
||||
local dir=$PWD testdir=
|
||||
while [[ $dir != / ]]; do
|
||||
if [[ -e $dir/justfile || -e $dir/.justfile || -e $dir/Justfile ]]; then
|
||||
testdir=$dir/pkg/integration/tests
|
||||
break
|
||||
fi
|
||||
dir=${dir:h}
|
||||
done
|
||||
if [[ -d $testdir ]]; then
|
||||
# A test's name is its path under pkg/integration/tests/ without
|
||||
# the .go extension, e.g. submodule/reset. Build that list, then
|
||||
# let _multi_parts complete it one "/"-separated segment at a
|
||||
# time, so an empty <Tab> offers only categories.
|
||||
local -a tests
|
||||
tests=($testdir/**/*.go(.N:r)) # strip the .go extension
|
||||
tests=(${tests#$testdir/}) # make relative to the tests dir
|
||||
tests=(${(M)tests:#*/*}) # keep category/name (drop top-level helpers)
|
||||
tests=(${tests:#shared/*}) # drop the cross-directory shared package
|
||||
tests=(${tests:#*/shared}) # drop per-category shared.go helpers
|
||||
local expl
|
||||
_wanted tests expl 'integration test' _multi_parts / tests
|
||||
return
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
_clap_dynamic_completer_just "$@"
|
||||
}
|
||||
|
||||
compdef _just_lazygit_e2e just # bind last so this wins over the default
|
||||
Loading…
Reference in a new issue