diff --git a/pkg/integration/components/runner.go b/pkg/integration/components/runner.go index 78cb5439f..aaaabd0a0 100644 --- a/pkg/integration/components/runner.go +++ b/pkg/integration/components/runner.go @@ -1,6 +1,7 @@ package components import ( + "errors" "fmt" "os" "os/exec" @@ -159,9 +160,7 @@ func prepareTestDir( return "", err } - workingDir := createFixture(test, paths, rootDir) - - return workingDir, nil + return createFixture(test, paths, rootDir) } func buildLazygit(testArgs RunTestArgs) error { @@ -182,22 +181,41 @@ func buildLazygit(testArgs RunTestArgs) error { return osCommand.Cmd.New(args).Run() } +// A failing setup step panics with this so that the remaining steps, which +// would only produce follow-on failures, are skipped. +type fixtureFailure string + // Sets up the fixture for test and returns the working directory to invoke // lazygit in. -func createFixture(test *IntegrationTest, paths Paths, rootDir string) string { +func createFixture(test *IntegrationTest, paths Paths, rootDir string) (workingDir string, err error) { + // Tests run as parallel subtests, and a panic escaping one of them takes + // down the whole test binary, discarding every other test's result along + // with it. Report a broken fixture as this test's error instead. + defer func() { + panicValue := recover() + if panicValue == nil { + return + } + failure, ok := panicValue.(fixtureFailure) + if !ok { + panic(panicValue) + } + err = errors.New(string(failure)) + }() + env := NewTestEnvironment(rootDir) env = append(env, fmt.Sprintf("%s=%s", PWD, paths.ActualRepo())) shell := NewShell( paths.ActualRepo(), env, - func(errorMsg string) { panic(errorMsg) }, + func(errorMsg string) { panic(fixtureFailure(errorMsg)) }, ) shell.Init() test.SetupRepo(shell) - return shell.dir + return shell.dir, nil } func testPath(rootdir string) string { diff --git a/pkg/integration/components/test_test.go b/pkg/integration/components/test_test.go index 3a145bf43..cf0338dec 100644 --- a/pkg/integration/components/test_test.go +++ b/pkg/integration/components/test_test.go @@ -1,8 +1,11 @@ package components import ( + "os" + "path/filepath" "testing" + lazycoreUtils "github.com/jesseduffield/lazycore/pkg/utils" "github.com/jesseduffield/lazygit/pkg/commands/git_commands" "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/config" @@ -158,6 +161,27 @@ func TestSuccess(t *testing.T) { assert.Equal(t, "", driver.failureMessage) } +func TestFailingFixture(t *testing.T) { + test := NewIntegrationTest(NewIntegrationTestArgs{ + Description: unitTestDescription, + SetupRepo: func(shell *Shell) { + shell.RunCommand([]string{"git", "checkout", "no-such-branch"}) + shell.CreateFile("reached.txt", "") + }, + Run: func(t *TestDriver, keys config.KeybindingConfig) {}, + }) + + paths := NewPaths(t.TempDir()) + assert.NoError(t, os.MkdirAll(paths.ActualRepo(), 0o777)) + + workingDir, err := createFixture(test, paths, lazycoreUtils.GetLazyRootDirectory()) + + assert.ErrorContains(t, err, "git checkout no-such-branch") + assert.Empty(t, workingDir) + // the steps following the failing one are skipped + assert.NoFileExists(t, filepath.Join(paths.ActualRepo(), "reached.txt")) +} + func TestGitVersionRestriction(t *testing.T) { scenarios := []struct { testName string