diff --git a/helpers.go b/helpers.go index 7354dc7dcf3967847a0bb540d0460c5f7e8272e1..93f26623bff2ca5fb6b7ba4e3bdfb34cf4a8a01f 100644 --- a/helpers.go +++ b/helpers.go @@ -8,16 +8,19 @@ import ( "github.com/stretchr/testify/require" ) -func PrintEnv(tests *Tests, t *testing.T, args []string) (err error) { - envs := os.Environ() - sort.Strings(envs) - for _, env := range envs { - t.Log(env) +func PrintEnv(tests *Tests, t *testing.T, args []string) { + if tests.Debug { + t.Helper() + envs := os.Environ() + sort.Strings(envs) + for _, env := range envs { + t.Log(env) + } } - return } -func TempFile(tests *Tests, t *testing.T, args []string) (err error) { +func TempFile(tests *Tests, t *testing.T, args []string) { + t.Helper() file, err := os.CreateTemp("", "test_") require.NoError(t, err) t.Cleanup(func() { @@ -25,5 +28,4 @@ func TempFile(tests *Tests, t *testing.T, args []string) (err error) { }) t.Logf("TempFile: %s=%s", args[0], file.Name()) t.Setenv(args[0], file.Name()) - return } diff --git a/snok.go b/snok.go index 756ab2fdb696eb5e44f2ffb8e8bf782cbd39a603..a94367276aae4a0e5c14899de512652c8cdb2144 100644 --- a/snok.go +++ b/snok.go @@ -16,7 +16,6 @@ import ( "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/stretchr/testify/require" - "github.com/testcontainers/testcontainers-go" "gonum.org/v1/gonum/graph" "gonum.org/v1/gonum/graph/simple" "gonum.org/v1/gonum/graph/topo" @@ -42,6 +41,12 @@ func NewTestSuite(cmd *cobra.Command) *Tests { flag.BoolVar(&ct.Debug, "debug", false, "debug") flag.BoolVar(&ct.Trace, "trace", false, "trace") flag.Parse() + if os.Getenv("SNOK_DEBUG") == "true" { + ct.Debug = true + } + if os.Getenv("SNOK_TRACE") == "true" { + ct.Trace = true + } return ct } @@ -56,12 +61,7 @@ func (ct *Tests) GetTest(name string) (*test, error) { return nil, fmt.Errorf("node type is not test: %s", name) } -func (ct *Tests) Accept(log testcontainers.Log) { - ct.t.Helper() - ct.t.Logf("%s", log.Content) -} - -func (tests *Tests) AddHelper(name string, fn func(*Tests, *testing.T, []string) error, needs ...string) *helper { +func (tests *Tests) AddHelper(name string, fn func(*Tests, *testing.T, []string), needs ...string) *helper { helper := &helper{ node: node{ Name: name, @@ -73,6 +73,10 @@ func (tests *Tests) AddHelper(name string, fn func(*Tests, *testing.T, []string) return helper } +func (tests *Tests) AddHelperCleanup(f func()) { + tests.t.Cleanup(f) +} + func (tests *Tests) addTests(t *testing.T, cmd *cobra.Command, cmds []string) { cmds = append(cmds, cmd.Name()) annotation, exists := cmd.Annotations["tests"] @@ -82,7 +86,7 @@ func (tests *Tests) addTests(t *testing.T, cmd *cobra.Command, cmds []string) { require.NoError(t, err, "Malformed annotation: %s", annotation) for _, test := range nodes { test.cmd = cmd - test.Args = append(cmds[1:], test.Args...) + test.cmds = cmds tests.graph.AddNode(&test) } } @@ -117,8 +121,9 @@ func (tests *Tests) Run(t *testing.T) { nodes := tests.calculateExecutionOrder(t) for _, node := range nodes { if helper, ok := node.(*helper); ok && helper.needed { - err := helper.fn(tests, t, helper.args) - require.NoError(t, err, "Failed to execute helper: %s", helper) + t.Run(fmt.Sprintf("[%s]", helper.Name), func(tt *testing.T) { + helper.fn(tests, t, helper.args) + }) } if test, ok := node.(*test); ok { tests.executeTest(t, test) @@ -147,7 +152,7 @@ func (tests *Tests) executeTest(t *testing.T, test *test) { } }() } - output, err := tests.executeCmd(test.Args, input) + output, err := tests.executeCmd(append(test.cmds[1:], test.Args...), input) resetFlags(t, test.cmd) if test.ExpectError { require.Error(t, err, "Expected error") diff --git a/snok_test.go b/snok_test.go index 2625dfc195cd644739e45b09d459981c22781900..e61f32f63f08ca05fc768e3a4291837f03c00517 100644 --- a/snok_test.go +++ b/snok_test.go @@ -5,11 +5,13 @@ import ( "errors" "fmt" "io" + "log" "os" "strings" "testing" "unicode" + "github.com/docker/docker/pkg/ioutils" "github.com/spf13/cobra" "github.com/stretchr/testify/require" "github.com/testcontainers/testcontainers-go" @@ -38,32 +40,37 @@ func TestMain(m *testing.M) { } func TestCmds(t *testing.T) { + testcontainers.Logger = log.New(&ioutils.NopWriter{}, "", 0) + if tests.Trace { + testcontainers.Logger = log.New(os.Stdout, " ", 0) + } tests.Run(t) } -func mockContainer(tests *Tests, t *testing.T, args []string) error { +func mockContainer(tests *Tests, t *testing.T, args []string) { if os.Getenv("MOCKSERVER_URL") == "" { ctx := context.Background() opts := []testcontainers.ContainerCustomizer{ testcontainers.WithImage("mockserver/mockserver:5.15.0"), - testcontainers.WithLogConsumers(tests), + } + if tests.Debug || tests.Trace { + opts = append(opts, testcontainers.WithLogConsumers(NewTestLogConsumer(t))) } mockserverContainer, err := mockserver.RunContainer(ctx, opts...) if err != nil && strings.Contains(err.Error(), "Cannot connect to the Docker daemon") { t.Skip("Docker not available") } require.NoError(t, err) - t.Cleanup(func() { - require.NoError(t, mockserverContainer.Terminate(ctx)) - }) url, err := mockserverContainer.URL(ctx) require.NoError(t, err) + tests.AddHelperCleanup(func() { + require.NoError(t, mockserverContainer.Terminate(ctx)) + }) t.Setenv("MOCKSERVER_URL", url) } - return nil } -func patchTestInput(tests *Tests, t *testing.T, args []string) error { +func patchTestInput(tests *Tests, t *testing.T, args []string) { _, err := tests.GetTest("TestContainer") require.Error(t, err) _, err = tests.GetTest("Does not exist") @@ -73,7 +80,6 @@ func patchTestInput(tests *Tests, t *testing.T, args []string) error { t.Logf("Modifying %s", test.String()) test.Input = &dashboardUrl require.NoError(t, err) - return nil } var rootCmd = &cobra.Command{ diff --git a/types.go b/types.go index bd5597f8967b6f94139e4454e9c45b8cc70e7107..40c2f5cf3b628c75736c93a5ad88a7462ca9c088 100644 --- a/types.go +++ b/types.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/spf13/cobra" + "github.com/testcontainers/testcontainers-go" "gonum.org/v1/gonum/graph" ) @@ -60,7 +61,7 @@ func (n *node) String() string { // helper node in the graph. type helper struct { node - fn func(*Tests, *testing.T, []string) error + fn func(*Tests, *testing.T, []string) args []string } @@ -72,8 +73,24 @@ func (h *helper) SetArgs(args ...string) { type test struct { node cmd *cobra.Command + cmds []string Args []string `json:"args,omitempty"` Input *string `json:"input,omitempty"` Output *string `json:"output,omitempty"` ExpectError bool `json:"expectError,omitempty"` } + +// TestLogConsumer consumes testcontainer logs. +type TestLogConsumer struct { + t *testing.T + testcontainers.LogConsumer +} + +func NewTestLogConsumer(t *testing.T) *TestLogConsumer { + return &TestLogConsumer{t: t} +} + +func (l *TestLogConsumer) Accept(log testcontainers.Log) { + l.t.Helper() + l.t.Logf("%s", log.Content) +}