From cb8c3b00020a0ceaafb071b58dbaa1970d3bdfa6 Mon Sep 17 00:00:00 2001 From: Earl Warren Date: Wed, 30 Jul 2025 13:58:35 +0000 Subject: [PATCH] feat(tests): cmd executeCommand captures stderr & stdout (#769) test only refactor that will be used by https://code.forgejo.org/forgejo/runner/pulls/757 - features - [PR](https://code.forgejo.org/forgejo/runner/pulls/769): feat(tests): cmd executeCommand captures stderr & stdout Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/769 Reviewed-by: Michael Kriese Co-authored-by: Earl Warren Co-committed-by: Earl Warren --- internal/app/cmd/create-runner-file_test.go | 17 +------ internal/app/cmd/main_test.go | 52 +++++++++++++++++++++ 2 files changed, 54 insertions(+), 15 deletions(-) create mode 100644 internal/app/cmd/main_test.go diff --git a/internal/app/cmd/create-runner-file_test.go b/internal/app/cmd/create-runner-file_test.go index 275b7101..4d786076 100644 --- a/internal/app/cmd/create-runner-file_test.go +++ b/internal/app/cmd/create-runner-file_test.go @@ -3,7 +3,6 @@ package cmd import ( - "bytes" "context" "os" "testing" @@ -14,27 +13,15 @@ import ( "code.forgejo.org/forgejo/runner/internal/pkg/ver" "connectrpc.com/connect" - "github.com/spf13/cobra" "github.com/stretchr/testify/assert" "gopkg.in/yaml.v3" ) -func executeCommand(ctx context.Context, cmd *cobra.Command, args ...string) (string, error) { - buf := new(bytes.Buffer) - cmd.SetOut(buf) - cmd.SetErr(buf) - cmd.SetArgs(args) - - err := cmd.ExecuteContext(ctx) - - return buf.String(), err -} - func Test_createRunnerFileCmd(t *testing.T) { configFile := "config.yml" ctx := context.Background() cmd := createRunnerFileCmd(ctx, &configFile) - output, err := executeCommand(ctx, cmd) + output, _, _, err := executeCommand(ctx, t, cmd) assert.ErrorContains(t, err, `required flag(s) "instance", "secret" not set`) assert.Contains(t, output, "Usage:") } @@ -89,7 +76,7 @@ func Test_runCreateRunnerFile(t *testing.T) { // ctx := context.Background() cmd := createRunnerFileCmd(ctx, &configFile) - output, err := executeCommand(ctx, cmd, "--connect", "--secret", secret, "--instance", instance, "--name", name) + output, _, _, err := executeCommand(ctx, t, cmd, "--connect", "--secret", secret, "--instance", instance, "--name", name) assert.NoError(t, err) assert.EqualValues(t, "", output) diff --git a/internal/app/cmd/main_test.go b/internal/app/cmd/main_test.go new file mode 100644 index 00000000..6283b8a4 --- /dev/null +++ b/internal/app/cmd/main_test.go @@ -0,0 +1,52 @@ +// Copyright 2025 The Forgejo Authors +// SPDX-License-Identifier: MIT + +package cmd + +import ( + "bytes" + "context" + "io" + "os" + "testing" + + "code.forgejo.org/forgejo/runner/testutils" + + "github.com/spf13/cobra" + "github.com/stretchr/testify/require" +) + +// Capture what's being written into a standard file descriptor. +func captureOutput(t *testing.T, stdFD *os.File) (finish func() (output string)) { + t.Helper() + + r, w, err := os.Pipe() + require.NoError(t, err) + resetStdout := testutils.MockVariable(stdFD, *w) + + return func() (output string) { + w.Close() + resetStdout() + + out, err := io.ReadAll(r) + require.NoError(t, err) + return string(out) + } +} + +func executeCommand(ctx context.Context, t *testing.T, cmd *cobra.Command, args ...string) (cmdOut, stdOut, stdErr string, err error) { + t.Helper() + finishStdout := captureOutput(t, os.Stdout) + finishStderr := captureOutput(t, os.Stderr) + buf := new(bytes.Buffer) + cmd.SetOut(buf) + cmd.SetErr(buf) + cmd.SetArgs(args) + + err = cmd.ExecuteContext(ctx) + + cmdOut = buf.String() + stdOut = finishStdout() + stdErr = finishStderr() + return cmdOut, stdOut, stdErr, err +}