fix mixed assertion libraries in tests

Before this, assertion libraries were mixed, sometimes
even in the same file.

    git grep -l '"gotest.tools/v3/' | wc -l
    75
    git grep -l '"github.com/stretchr/testify' | wc -l
    24

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2026-03-30 00:22:44 +02:00 committed by Guillaume Lours
parent a97738de7d
commit 92a7ac1fa2
31 changed files with 274 additions and 268 deletions

View file

@ -39,6 +39,12 @@ linters:
desc: use stdlib slices package
- pkg: gopkg.in/yaml.v2
desc: compose-go uses yaml.v3
- pkg: github.com/stretchr/testify/assert
desc: Use "gotest.tools/v3/assert" instead
- pkg: github.com/stretchr/testify/require
desc: Use "gotest.tools/v3/assert" instead
- pkg: github.com/stretchr/testify/suite
desc: Do not use
forbidigo:
analyze-types: true
forbid:

View file

@ -27,8 +27,8 @@ import (
"github.com/compose-spec/compose-go/v2/types"
"github.com/docker/cli/cli/streams"
"github.com/stretchr/testify/require"
"go.uber.org/mock/gomock"
"gotest.tools/v3/assert"
"github.com/docker/compose/v5/pkg/mocks"
)
@ -56,15 +56,14 @@ func TestApplyPlatforms_InferFromRuntime(t *testing.T) {
t.Run("SinglePlatform", func(t *testing.T) {
project := makeProject()
require.NoError(t, applyPlatforms(project, true))
require.EqualValues(t, []string{"alice/32"}, project.Services["test"].Build.Platforms)
assert.NilError(t, applyPlatforms(project, true))
assert.DeepEqual(t, types.StringList{"alice/32"}, project.Services["test"].Build.Platforms)
})
t.Run("MultiPlatform", func(t *testing.T) {
project := makeProject()
require.NoError(t, applyPlatforms(project, false))
require.EqualValues(t, []string{"linux/amd64", "linux/arm64", "alice/32"},
project.Services["test"].Build.Platforms)
assert.NilError(t, applyPlatforms(project, false))
assert.DeepEqual(t, types.StringList{"linux/amd64", "linux/arm64", "alice/32"}, project.Services["test"].Build.Platforms)
})
}
@ -92,15 +91,14 @@ func TestApplyPlatforms_DockerDefaultPlatform(t *testing.T) {
t.Run("SinglePlatform", func(t *testing.T) {
project := makeProject()
require.NoError(t, applyPlatforms(project, true))
require.EqualValues(t, []string{"linux/amd64"}, project.Services["test"].Build.Platforms)
assert.NilError(t, applyPlatforms(project, true))
assert.DeepEqual(t, types.StringList{"linux/amd64"}, project.Services["test"].Build.Platforms)
})
t.Run("MultiPlatform", func(t *testing.T) {
project := makeProject()
require.NoError(t, applyPlatforms(project, false))
require.EqualValues(t, []string{"linux/amd64", "linux/arm64"},
project.Services["test"].Build.Platforms)
assert.NilError(t, applyPlatforms(project, false))
assert.DeepEqual(t, types.StringList{"linux/amd64", "linux/arm64"}, project.Services["test"].Build.Platforms)
})
}
@ -128,13 +126,13 @@ func TestApplyPlatforms_UnsupportedPlatform(t *testing.T) {
t.Run("SinglePlatform", func(t *testing.T) {
project := makeProject()
require.EqualError(t, applyPlatforms(project, true),
assert.Error(t, applyPlatforms(project, true),
`service "test" build.platforms does not support value set by DOCKER_DEFAULT_PLATFORM: commodore/64`)
})
t.Run("MultiPlatform", func(t *testing.T) {
project := makeProject()
require.EqualError(t, applyPlatforms(project, false),
assert.Error(t, applyPlatforms(project, false),
`service "test" build.platforms does not support value set by DOCKER_DEFAULT_PLATFORM: commodore/64`)
})
}
@ -179,7 +177,7 @@ func TestIsRemoteConfig(t *testing.T) {
},
}
got := isRemoteConfig(cli, opts)
require.Equal(t, tt.want, got)
assert.Equal(t, tt.want, got)
})
}
}
@ -206,7 +204,7 @@ func TestDisplayLocationRemoteStack(t *testing.T) {
displayLocationRemoteStack(cli, project, options)
output := buf.String()
require.Equal(t, output, fmt.Sprintf("Your compose stack %q is stored in %q\n", "oci://registry.example.com/stack:latest", "/tmp/test"))
assert.Equal(t, output, fmt.Sprintf("Your compose stack %q is stored in %q\n", "oci://registry.example.com/stack:latest", "/tmp/test"))
}
func TestDisplayInterpolationVariables(t *testing.T) {
@ -227,7 +225,7 @@ services:
- UNSET_VAR # optional without default
`
composePath := filepath.Join(tmpDir, "docker-compose.yml")
require.NoError(t, os.WriteFile(composePath, []byte(composeContent), 0o644))
assert.NilError(t, os.WriteFile(composePath, []byte(composeContent), 0o644))
buf := new(bytes.Buffer)
cli := mocks.NewMockCli(ctrl)
@ -244,8 +242,8 @@ services:
// Extract variables from the model
info, noVariables, err := extractInterpolationVariablesFromModel(t.Context(), cli, projectOptions, []string{})
require.NoError(t, err)
require.False(t, noVariables)
assert.NilError(t, err)
assert.Assert(t, noVariables == false)
// Display the variables
displayInterpolationVariables(cli.Out(), info)
@ -267,7 +265,7 @@ services:
actualOutput := buf.String()
// Compare normalized strings
require.Equal(t,
assert.Equal(t,
normalizeSpaces(expected),
normalizeSpaces(actualOutput),
"\nExpected:\n%s\nGot:\n%s", expected, actualOutput)
@ -370,14 +368,13 @@ func TestConfirmRemoteIncludes(t *testing.T) {
err := confirmRemoteIncludes(cli, tt.opts, tt.assumeYes)
if tt.wantErr {
require.Error(t, err)
require.Equal(t, tt.errMessage, err.Error())
assert.Error(t, err, tt.errMessage)
} else {
require.NoError(t, err)
assert.NilError(t, err)
}
if tt.wantOutput != "" {
require.Equal(t, tt.wantOutput, buf.String())
assert.Equal(t, tt.wantOutput, buf.String())
}
buf.Reset()
})

View file

@ -21,8 +21,7 @@ import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gotest.tools/v3/assert"
"github.com/docker/compose/v5/pkg/api"
)
@ -221,20 +220,20 @@ func TestRunTopCore(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
header, entries := collectTop([]api.ContainerProcSummary{summary})
assert.Equal(t, tc.header, header)
assert.Equal(t, tc.entries, entries)
assert.DeepEqual(t, tc.header, header)
assert.DeepEqual(t, tc.entries, entries)
var buf bytes.Buffer
err := topPrint(&buf, header, entries)
require.NoError(t, err)
assert.NilError(t, err)
assert.Equal(t, tc.output, buf.String())
})
}
t.Run("all", func(t *testing.T) {
header, entries := collectTop(all)
assert.Equal(t, topHeader{
assert.DeepEqual(t, topHeader{
"SERVICE": 0,
"#": 1,
"UID": 2,
@ -247,7 +246,7 @@ func TestRunTopCore(t *testing.T) {
"GID": 9,
"CMD": 10,
}, header)
assert.Equal(t, []topEntries{
assert.DeepEqual(t, []topEntries{
{
"SERVICE": "simple",
"#": "1",
@ -308,7 +307,7 @@ func TestRunTopCore(t *testing.T) {
var buf bytes.Buffer
err := topPrint(&buf, header, entries)
require.NoError(t, err)
assert.NilError(t, err)
assert.Equal(t, trim(`
SERVICE # UID PID PPID C STIME TTY TIME GID CMD
simple 1 root 1 1 0 12:00 ? 00:00:01 - /entrypoint

View file

@ -19,8 +19,7 @@ package compose
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gotest.tools/v3/assert"
)
func TestPreferredIndentationStr(t *testing.T) {
@ -84,10 +83,10 @@ func TestPreferredIndentationStr(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
got, err := preferredIndentationStr(tt.args.size, tt.args.useSpace)
if tt.wantErr {
require.Errorf(t, err, "preferredIndentationStr(%v, %v)", tt.args.size, tt.args.useSpace)
assert.ErrorContains(t, err, "invalid indentation size", "preferredIndentationStr(%v,%v)", tt.args.size, tt.args.useSpace)
} else {
require.NoError(t, err)
assert.Equalf(t, tt.want, got, "preferredIndentationStr(%v, %v)", tt.args.size, tt.args.useSpace)
assert.NilError(t, err)
assert.Equal(t, tt.want, got)
}
})
}

3
go.mod
View file

@ -43,7 +43,6 @@ require (
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966
github.com/spf13/cobra v1.10.2
github.com/spf13/pflag v1.0.10
github.com/stretchr/testify v1.11.1
github.com/tilt-dev/fsnotify v1.4.8-0.20220602155310-fff9c274a375
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0
go.opentelemetry.io/otel v1.42.0
@ -73,7 +72,6 @@ require (
github.com/containerd/ttrpc v1.2.7 // indirect
github.com/containerd/typeurl/v2 v2.2.3 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/docker/distribution v2.8.3+incompatible // indirect
github.com/docker/docker-credential-helpers v0.9.5 // indirect
github.com/docker/go-connections v0.6.0 // indirect
@ -113,7 +111,6 @@ require (
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 // indirect

View file

@ -21,7 +21,7 @@ import (
"testing"
"time"
"github.com/stretchr/testify/require"
"gotest.tools/v3/assert"
)
func TestClientPing(t *testing.T) {
@ -41,8 +41,8 @@ func TestClientPing(t *testing.T) {
now := time.Now()
ret, err := client.Ping(t.Context())
require.NoError(t, err)
assert.NilError(t, err)
serverTime := time.Unix(0, ret.ServerTime)
require.True(t, now.Before(serverTime))
assert.Assert(t, now.Before(serverTime))
}

View file

@ -20,7 +20,7 @@ import (
"testing"
"github.com/compose-spec/compose-go/v2/types"
"github.com/stretchr/testify/require"
"gotest.tools/v3/assert"
)
func TestProjectHash(t *testing.T) {
@ -53,15 +53,15 @@ func TestProjectHash(t *testing.T) {
}
hashA, ok := projectHash(projA)
require.True(t, ok)
require.NotEmpty(t, hashA)
assert.Assert(t, ok)
assert.Assert(t, hashA != "")
hashB, ok := projectHash(projB)
require.True(t, ok)
require.NotEmpty(t, hashB)
require.Equal(t, hashA, hashB)
assert.Assert(t, ok)
assert.Assert(t, hashB != "")
assert.Equal(t, hashA, hashB)
hashC, ok := projectHash(projC)
require.True(t, ok)
require.NotEmpty(t, hashC)
require.NotEqual(t, hashC, hashA)
assert.Assert(t, ok)
assert.Assert(t, hashC != "")
assert.Assert(t, hashC != hashA)
}

View file

@ -21,7 +21,7 @@ import (
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/context/store"
"github.com/stretchr/testify/require"
"gotest.tools/v3/assert"
"github.com/docker/compose/v5/internal/tracing"
)
@ -52,9 +52,9 @@ func TestExtractOtelFromContext(t *testing.T) {
},
Endpoints: make(map[string]any),
})
require.NoError(t, err)
assert.NilError(t, err)
cfg, err := tracing.ConfigFromDockerContext(st, "test")
require.NoError(t, err)
require.Equal(t, "localhost:1234", cfg.Endpoint)
assert.NilError(t, err)
assert.Equal(t, "localhost:1234", cfg.Endpoint)
}

View file

@ -24,9 +24,8 @@ import (
"testing"
"github.com/compose-spec/compose-go/v2/types"
testify "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
"github.com/docker/compose/v5/pkg/utils"
)
@ -85,11 +84,11 @@ func TestTraversalWithMultipleParents(t *testing.T) {
svc <- service
return nil
})
require.NoError(t, err, "Error during iteration")
assert.NilError(t, err, "Error during iteration")
close(svc)
<-done
testify.Len(t, seen, 101)
assert.Check(t, is.Len(seen, 101))
for svc, count := range seen {
assert.Equal(t, 1, count, "Service: %s", svc)
}
@ -101,8 +100,8 @@ func TestInDependencyUpCommandOrder(t *testing.T) {
order = append(order, service)
return nil
})
require.NoError(t, err, "Error during iteration")
require.Equal(t, []string{"test3", "test2", "test1"}, order)
assert.NilError(t, err, "Error during iteration")
assert.DeepEqual(t, []string{"test3", "test2", "test1"}, order)
}
func TestInDependencyReverseDownCommandOrder(t *testing.T) {
@ -111,8 +110,8 @@ func TestInDependencyReverseDownCommandOrder(t *testing.T) {
order = append(order, service)
return nil
})
require.NoError(t, err, "Error during iteration")
require.Equal(t, []string{"test1", "test2", "test3"}, order)
assert.NilError(t, err, "Error during iteration")
assert.DeepEqual(t, []string{"test1", "test2", "test3"}, order)
}
func TestBuildGraph(t *testing.T) {

View file

@ -22,8 +22,8 @@ import (
"testing"
"github.com/compose-spec/compose-go/v2/cli"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
"github.com/docker/compose/v5/pkg/api"
)
@ -45,10 +45,10 @@ services:
POSTGRES_PASSWORD: secret
`
err := os.WriteFile(composeFile, []byte(composeContent), 0o644)
require.NoError(t, err)
assert.NilError(t, err)
service, err := NewComposeService(nil)
require.NoError(t, err)
assert.NilError(t, err)
// Load the project
project, err := service.LoadProject(t.Context(), api.ProjectLoadOptions{
@ -56,12 +56,11 @@ services:
})
// Assertions
require.NoError(t, err)
assert.NotNil(t, project)
assert.NilError(t, err)
assert.Equal(t, "test-project", project.Name)
assert.Len(t, project.Services, 2)
assert.Contains(t, project.Services, "web")
assert.Contains(t, project.Services, "db")
assert.Assert(t, is.Len(project.Services, 2))
assert.Check(t, is.Contains(project.Services, "web"))
assert.Check(t, is.Contains(project.Services, "db"))
// Check labels were applied
webService := project.Services["web"]
@ -81,26 +80,26 @@ services:
- LITERAL_VAR=literal_value
`
err := os.WriteFile(composeFile, []byte(composeContent), 0o644)
require.NoError(t, err)
assert.NilError(t, err)
// Set environment variable
t.Setenv("TEST_VAR", "resolved_value")
service, err := NewComposeService(nil)
require.NoError(t, err)
assert.NilError(t, err)
// Test with environment resolution (default)
t.Run("WithResolution", func(t *testing.T) {
project, err := service.LoadProject(t.Context(), api.ProjectLoadOptions{
ConfigPaths: []string{composeFile},
})
require.NoError(t, err)
assert.NilError(t, err)
appService := project.Services["app"]
// Environment should be resolved
assert.NotNil(t, appService.Environment["TEST_VAR"])
assert.Assert(t, appService.Environment["TEST_VAR"] != nil)
assert.Equal(t, "resolved_value", *appService.Environment["TEST_VAR"])
assert.NotNil(t, appService.Environment["LITERAL_VAR"])
assert.Assert(t, appService.Environment["LITERAL_VAR"] != nil)
assert.Equal(t, "literal_value", *appService.Environment["LITERAL_VAR"])
})
@ -110,12 +109,12 @@ services:
ConfigPaths: []string{composeFile},
ProjectOptionsFns: []cli.ProjectOptionsFn{cli.WithoutEnvironmentResolution},
})
require.NoError(t, err)
assert.NilError(t, err)
appService := project.Services["app"]
// Environment should NOT be resolved, keeping raw values
// Note: This depends on compose-go behavior, which may still have some resolution
assert.NotNil(t, appService.Environment)
assert.Assert(t, appService.Environment != nil)
})
}
@ -132,10 +131,10 @@ services:
image: redis:latest
`
err := os.WriteFile(composeFile, []byte(composeContent), 0o644)
require.NoError(t, err)
assert.NilError(t, err)
service, err := NewComposeService(nil)
require.NoError(t, err)
assert.NilError(t, err)
// Load only specific services
project, err := service.LoadProject(t.Context(), api.ProjectLoadOptions{
@ -143,11 +142,11 @@ services:
Services: []string{"web", "db"},
})
require.NoError(t, err)
assert.Len(t, project.Services, 2)
assert.Contains(t, project.Services, "web")
assert.Contains(t, project.Services, "db")
assert.NotContains(t, project.Services, "cache")
assert.NilError(t, err)
assert.Check(t, is.Len(project.Services, 2))
assert.Check(t, is.Contains(project.Services, "web"))
assert.Check(t, is.Contains(project.Services, "db"))
assert.Check(t, !is.Contains(project.Services, "cache")().Success())
}
func TestLoadProject_WithProfiles(t *testing.T) {
@ -162,19 +161,19 @@ services:
profiles: ["debug"]
`
err := os.WriteFile(composeFile, []byte(composeContent), 0o644)
require.NoError(t, err)
assert.NilError(t, err)
service, err := NewComposeService(nil)
require.NoError(t, err)
assert.NilError(t, err)
// Without debug profile
t.Run("WithoutProfile", func(t *testing.T) {
project, err := service.LoadProject(t.Context(), api.ProjectLoadOptions{
ConfigPaths: []string{composeFile},
})
require.NoError(t, err)
assert.Len(t, project.Services, 1)
assert.Contains(t, project.Services, "web")
assert.NilError(t, err)
assert.Check(t, is.Len(project.Services, 1))
assert.Check(t, is.Contains(project.Services, "web"))
})
// With debug profile
@ -183,10 +182,10 @@ services:
ConfigPaths: []string{composeFile},
Profiles: []string{"debug"},
})
require.NoError(t, err)
assert.Len(t, project.Services, 2)
assert.Contains(t, project.Services, "web")
assert.Contains(t, project.Services, "debug")
assert.NilError(t, err)
assert.Check(t, is.Len(project.Services, 2))
assert.Check(t, is.Contains(project.Services, "web"))
assert.Check(t, is.Contains(project.Services, "debug"))
})
}
@ -199,10 +198,10 @@ services:
image: nginx:latest
`
err := os.WriteFile(composeFile, []byte(composeContent), 0o644)
require.NoError(t, err)
assert.NilError(t, err)
service, err := NewComposeService(nil)
require.NoError(t, err)
assert.NilError(t, err)
// Track events received
var events []string
@ -215,8 +214,8 @@ services:
LoadListeners: []api.LoadListener{listener},
})
require.NoError(t, err)
assert.NotNil(t, project)
assert.NilError(t, err)
assert.Assert(t, project != nil)
// Listeners should have been called (exact events depend on compose-go implementation)
// The slice itself is always initialized (non-nil), even if empty
@ -232,19 +231,19 @@ services:
image: nginx:latest
`
err := os.WriteFile(composeFile, []byte(composeContent), 0o644)
require.NoError(t, err)
assert.NilError(t, err)
service, err := NewComposeService(nil)
require.NoError(t, err)
assert.NilError(t, err)
// Without explicit project name
t.Run("InferredName", func(t *testing.T) {
project, err := service.LoadProject(t.Context(), api.ProjectLoadOptions{
ConfigPaths: []string{composeFile},
})
require.NoError(t, err)
assert.NilError(t, err)
// Project name should be inferred from directory
assert.NotEmpty(t, project.Name)
assert.Assert(t, project.Name != "")
})
// With explicit project name
@ -253,7 +252,7 @@ services:
ConfigPaths: []string{composeFile},
ProjectName: "my-custom-project",
})
require.NoError(t, err)
assert.NilError(t, err)
assert.Equal(t, "my-custom-project", project.Name)
})
}
@ -267,10 +266,10 @@ services:
image: nginx:latest
`
err := os.WriteFile(composeFile, []byte(composeContent), 0o644)
require.NoError(t, err)
assert.NilError(t, err)
service, err := NewComposeService(nil)
require.NoError(t, err)
assert.NilError(t, err)
// With compatibility mode
project, err := service.LoadProject(t.Context(), api.ProjectLoadOptions{
@ -278,8 +277,8 @@ services:
Compatibility: true,
})
require.NoError(t, err)
assert.NotNil(t, project)
assert.NilError(t, err)
assert.Assert(t, project != nil)
// In compatibility mode, separator should be "_"
assert.Equal(t, "_", api.Separator)
@ -294,29 +293,29 @@ func TestLoadProject_InvalidComposeFile(t *testing.T) {
this is not valid yaml: [[[
`
err := os.WriteFile(composeFile, []byte(composeContent), 0o644)
require.NoError(t, err)
assert.NilError(t, err)
service, err := NewComposeService(nil)
require.NoError(t, err)
assert.NilError(t, err)
// Should return an error for invalid YAML
project, err := service.LoadProject(t.Context(), api.ProjectLoadOptions{
ConfigPaths: []string{composeFile},
})
require.Error(t, err)
assert.Nil(t, project)
assert.Assert(t, err != nil)
assert.Assert(t, project == nil)
}
func TestLoadProject_MissingComposeFile(t *testing.T) {
service, err := NewComposeService(nil)
require.NoError(t, err)
assert.NilError(t, err)
// Should return an error for missing file
project, err := service.LoadProject(t.Context(), api.ProjectLoadOptions{
ConfigPaths: []string{"/nonexistent/compose.yaml"},
})
require.Error(t, err)
assert.Nil(t, project)
assert.Assert(t, err != nil)
assert.Assert(t, project == nil)
}

View file

@ -26,9 +26,9 @@ import (
"github.com/docker/docker/pkg/stdcopy"
containerType "github.com/moby/moby/api/types/container"
"github.com/moby/moby/client"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/mock/gomock"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
compose "github.com/docker/compose/v5/pkg/api"
)
@ -39,7 +39,7 @@ func TestComposeService_Logs_Demux(t *testing.T) {
api, cli := prepareMocks(mockCtrl)
tested, err := NewComposeService(cli)
require.NoError(t, err)
assert.NilError(t, err)
name := strings.ToLower(testProject)
@ -72,9 +72,9 @@ func TestComposeService_Logs_Demux(t *testing.T) {
c1Stderr := stdcopy.NewStdWriter(c1Writer, stdcopy.Stderr)
go func() {
_, err := c1Stdout.Write([]byte("hello stdout\n"))
assert.NoError(t, err, "Writing to fake stdout")
assert.NilError(t, err, "Writing to fake stdout")
_, err = c1Stderr.Write([]byte("hello stderr\n"))
assert.NoError(t, err, "Writing to fake stderr")
assert.NilError(t, err, "Writing to fake stderr")
_ = c1Writer.Close()
}()
api.EXPECT().ContainerLogs(anyCancellableContext(), "c", gomock.Any()).
@ -90,13 +90,8 @@ func TestComposeService_Logs_Demux(t *testing.T) {
consumer := &testLogConsumer{}
err = tested.Logs(t.Context(), name, consumer, opts)
require.NoError(t, err)
require.Equal(
t,
[]string{"hello stdout", "hello stderr"},
consumer.LogsForContainer("c"),
)
assert.NilError(t, err)
assert.DeepEqual(t, []string{"hello stdout", "hello stderr"}, consumer.LogsForContainer("c"))
}
// TestComposeService_Logs_ServiceFiltering ensures that we do not include
@ -112,7 +107,7 @@ func TestComposeService_Logs_ServiceFiltering(t *testing.T) {
api, cli := prepareMocks(mockCtrl)
tested, err := NewComposeService(cli)
require.NoError(t, err)
assert.NilError(t, err)
name := strings.ToLower(testProject)
@ -163,12 +158,12 @@ func TestComposeService_Logs_ServiceFiltering(t *testing.T) {
Project: proj,
}
err = tested.Logs(t.Context(), name, consumer, opts)
require.NoError(t, err)
assert.NilError(t, err)
require.Equal(t, []string{"hello c1"}, consumer.LogsForContainer("c1"))
require.Equal(t, []string{"hello c2"}, consumer.LogsForContainer("c2"))
require.Empty(t, consumer.LogsForContainer("c3"))
require.Equal(t, []string{"hello c4"}, consumer.LogsForContainer("c4"))
assert.Assert(t, is.DeepEqual([]string{"hello c1"}, consumer.LogsForContainer("c1")))
assert.Assert(t, is.DeepEqual([]string{"hello c2"}, consumer.LogsForContainer("c2")))
assert.Assert(t, is.Len(consumer.LogsForContainer("c3"), 0))
assert.Assert(t, is.DeepEqual([]string{"hello c4"}, consumer.LogsForContainer("c4")))
}
type testLogConsumer struct {

View file

@ -21,9 +21,9 @@ import (
"testing"
"github.com/compose-spec/compose-go/v2/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/mock/gomock"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
compose "github.com/docker/compose/v5/pkg/api"
"github.com/docker/compose/v5/pkg/mocks"
@ -116,7 +116,7 @@ func TestViz(t *testing.T) {
defer mockCtrl.Finish()
cli := mocks.NewMockCli(mockCtrl)
tested, err := NewComposeService(cli)
require.NoError(t, err)
assert.NilError(t, err)
t.Run("viz (no ports, networks or image)", func(t *testing.T) {
graphStr, err := tested.Viz(t.Context(), &project, compose.VizOptions{
@ -125,24 +125,24 @@ func TestViz(t *testing.T) {
IncludeImageName: false,
IncludeNetworks: false,
})
require.NoError(t, err, "viz command failed")
assert.NilError(t, err, "viz command failed")
// check indentation
assert.Contains(t, graphStr, "\n ", graphStr)
assert.NotContains(t, graphStr, "\n ", graphStr)
assert.Check(t, is.Contains(graphStr, "\n "))
assert.Check(t, !is.Contains(graphStr, "\n ")().Success(), graphStr)
// check digraph name
assert.Contains(t, graphStr, "digraph \""+project.Name+"\"", graphStr)
assert.Check(t, is.Contains(graphStr, "digraph \""+project.Name+"\""))
// check nodes
for _, service := range project.Services {
assert.Contains(t, graphStr, "\""+service.Name+"\" [style=\"filled\"", graphStr)
assert.Check(t, is.Contains(graphStr, "\""+service.Name+"\" [style=\"filled\""))
}
// check node attributes
assert.NotContains(t, graphStr, "Networks", graphStr)
assert.NotContains(t, graphStr, "Image", graphStr)
assert.NotContains(t, graphStr, "Ports", graphStr)
assert.Check(t, !is.Contains(graphStr, "Networks")().Success())
assert.Check(t, !is.Contains(graphStr, "Image")().Success())
assert.Check(t, !is.Contains(graphStr, "Ports")().Success())
// check edges that SHOULD exist in the generated graph
allowedEdges := make(map[string][]string)
@ -155,7 +155,7 @@ func TestViz(t *testing.T) {
}
for serviceName, dependencies := range allowedEdges {
for _, dependencyName := range dependencies {
assert.Contains(t, graphStr, "\""+serviceName+"\" -> \""+dependencyName+"\"", graphStr)
assert.Check(t, is.Contains(graphStr, "\""+serviceName+"\" -> \""+dependencyName+"\""))
}
}
@ -172,7 +172,7 @@ func TestViz(t *testing.T) {
}
for serviceName, forbiddenDeps := range forbiddenEdges {
for _, forbiddenDep := range forbiddenDeps {
assert.NotContains(t, graphStr, "\""+serviceName+"\" -> \""+forbiddenDep+"\"")
assert.Check(t, !is.Contains(graphStr, "\""+serviceName+"\" -> \""+forbiddenDep+"\"")().Success())
}
}
})
@ -184,32 +184,33 @@ func TestViz(t *testing.T) {
IncludeImageName: true,
IncludeNetworks: true,
})
require.NoError(t, err, "viz command failed")
assert.NilError(t, err, "viz command failed")
// check indentation
assert.Contains(t, graphStr, "\n\t", graphStr)
assert.NotContains(t, graphStr, "\n\t\t", graphStr)
assert.Check(t, is.Contains(graphStr, "\n\t"))
assert.Check(t, !is.Contains(graphStr, "\n\t\t")().Success(), graphStr)
// check digraph name
assert.Contains(t, graphStr, "digraph \""+project.Name+"\"", graphStr)
assert.Check(t, is.Contains(graphStr, "digraph \""+project.Name+"\""))
// check nodes
for _, service := range project.Services {
assert.Contains(t, graphStr, "\""+service.Name+"\" [style=\"filled\"", graphStr)
assert.Check(t, is.Contains(graphStr, "\""+service.Name+"\" [style=\"filled\""))
}
// check node attributes
assert.Contains(t, graphStr, "Networks", graphStr)
assert.Contains(t, graphStr, ">internal<", graphStr)
assert.Contains(t, graphStr, ">external<", graphStr)
assert.Contains(t, graphStr, "Image", graphStr)
assert.Check(t, is.Contains(graphStr, "Networks"))
assert.Check(t, is.Contains(graphStr, ">internal<"))
assert.Check(t, is.Contains(graphStr, ">external<"))
assert.Check(t, is.Contains(graphStr, "Image"))
for _, service := range project.Services {
assert.Contains(t, graphStr, ">"+service.Image+"<", graphStr)
assert.Check(t, is.Contains(graphStr, ">"+service.Image+"<"))
}
assert.Contains(t, graphStr, "Ports", graphStr)
assert.Check(t, is.Contains(graphStr, "Ports"))
for _, service := range project.Services {
for _, portConfig := range service.Ports {
assert.NotContains(t, graphStr, ">"+portConfig.Published+":"+strconv.Itoa(int(portConfig.Target))+"<", graphStr)
notContains := !is.Contains(graphStr, ">"+portConfig.Published+":"+strconv.Itoa(int(portConfig.Target))+"<")().Success()
assert.Check(t, notContains, graphStr)
}
}
})

View file

@ -15,9 +15,11 @@
package compose
import (
"cmp"
"context"
"fmt"
"os"
"slices"
"testing"
"time"
@ -27,7 +29,6 @@ import (
"github.com/moby/moby/api/types/container"
"github.com/moby/moby/api/types/image"
"github.com/moby/moby/client"
"github.com/stretchr/testify/require"
"go.uber.org/mock/gomock"
"gotest.tools/v3/assert"
@ -153,10 +154,14 @@ func TestWatch_Sync(t *testing.T) {
clock.Advance(watch.QuietPeriod)
select {
case actual := <-syncer.synced:
require.ElementsMatch(t, []*sync.PathMapping{
expected := []*sync.PathMapping{
{HostPath: "/sync/changed", ContainerPath: "/work/changed"},
{HostPath: "/sync/changed/sub", ContainerPath: "/work/changed/sub"},
}, actual)
}
slices.SortFunc(actual, func(a, b *sync.PathMapping) int {
return cmp.Compare(a.HostPath, b.HostPath)
})
assert.DeepEqual(t, expected, actual)
case <-time.After(100 * time.Millisecond):
t.Error("timeout")
}

View file

@ -21,7 +21,8 @@ import (
"strings"
"testing"
"github.com/stretchr/testify/require"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
)
// RequireServiceState ensures that the container is in the expected state
@ -30,15 +31,12 @@ func RequireServiceState(t testing.TB, cli *CLI, service string, state string) {
t.Helper()
psRes := cli.RunDockerComposeCmd(t, "ps", "--all", "--format=json", service)
var svc map[string]any
require.NoError(t, json.Unmarshal([]byte(psRes.Stdout()), &svc),
assert.NilError(t, json.Unmarshal([]byte(psRes.Stdout()), &svc),
"Invalid `compose ps` JSON: command output: %s",
psRes.Combined())
require.Equal(t, service, svc["Service"],
"Found ps output for unexpected service")
require.Equalf(t,
strings.ToLower(state),
strings.ToLower(svc["State"].(string)),
assert.Assert(t, is.Equal(service, svc["Service"]), "Found ps output for unexpected service")
assert.Assert(t, is.Equal(strings.ToLower(state), strings.ToLower(svc["State"].(string))),
"Service %q (%s) not in expected state",
service, svc["Name"],
)

View file

@ -27,8 +27,8 @@ import (
"testing"
"time"
"github.com/stretchr/testify/require"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
"gotest.tools/v3/icmd"
"gotest.tools/v3/poll"
)
@ -244,7 +244,7 @@ func TestBuildImageDependencies(t *testing.T) {
cli.RunDockerComposeCmd(t, "down", "--rmi=all", "-t=0")
res := cli.RunDockerOrExitError(t, "image", "rm", "build-dependencies-service")
if res.Error != nil {
require.Contains(t, res.Stderr(), `No such image: build-dependencies-service`)
assert.Assert(t, is.Contains(res.Stderr(), `No such image: build-dependencies-service`))
}
}
resetState()

View file

@ -25,8 +25,8 @@ import (
"testing"
"time"
testify "github.com/stretchr/testify/assert"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
"gotest.tools/v3/icmd"
)
@ -166,7 +166,7 @@ func TestInitContainer(t *testing.T) {
res := c.RunDockerComposeCmd(t, "--ansi=never", "--project-directory", "./fixtures/init-container", "up", "--menu=false")
defer c.RunDockerComposeCmd(t, "-p", "init-container", "down")
testify.Regexp(t, "foo-1 | hello(?m:.*)bar-1 | world", res.Stdout())
assert.Assert(t, is.Regexp("foo-1 | hello(?m:.*)bar-1 | world", res.Stdout()))
}
func TestRm(t *testing.T) {

View file

@ -31,7 +31,6 @@ import (
"time"
cp "github.com/otiai10/copy"
"github.com/stretchr/testify/require"
"gotest.tools/v3/assert"
"gotest.tools/v3/icmd"
"gotest.tools/v3/poll"
@ -148,7 +147,7 @@ func initializePlugins(t testing.TB, configDir string) {
}
})
require.NoError(t, os.MkdirAll(filepath.Join(configDir, "cli-plugins"), 0o755),
assert.NilError(t, os.MkdirAll(filepath.Join(configDir, "cli-plugins"), 0o755),
"Failed to create cli-plugins directory")
composePlugin, err := findExecutable(DockerComposeExecutableName)
if errors.Is(err, fs.ErrNotExist) {
@ -178,11 +177,11 @@ func initializePlugins(t testing.TB, configDir string) {
func initializeContextDir(t testing.TB, configDir string) {
dockerUserDir := ".docker/contexts"
userDir, err := os.UserHomeDir()
require.NoError(t, err, "Failed to get user home directory")
assert.NilError(t, err, "Failed to get user home directory")
userContextsDir := filepath.Join(userDir, dockerUserDir)
if checkExists(userContextsDir) {
dstContexts := filepath.Join(configDir, "contexts")
require.NoError(t, cp.Copy(userContextsDir, dstContexts), "Failed to copy contexts directory")
assert.NilError(t, cp.Copy(userContextsDir, dstContexts), "Failed to copy contexts directory")
}
}
@ -249,17 +248,17 @@ func CopyFile(t testing.TB, sourceFile string, destinationFile string) {
t.Helper()
src, err := os.Open(sourceFile)
require.NoError(t, err, "Failed to open source file: %s")
assert.NilError(t, err, "Failed to open source file: %s")
//nolint:errcheck
defer src.Close()
dst, err := os.OpenFile(destinationFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o755)
require.NoError(t, err, "Failed to open destination file: %s", destinationFile)
assert.NilError(t, err, "Failed to open destination file: %s", destinationFile)
//nolint:errcheck
defer dst.Close()
_, err = io.Copy(dst, src)
require.NoError(t, err, "Failed to copy file: %s", sourceFile)
assert.NilError(t, err, "Failed to copy file: %s", sourceFile)
}
// BaseEnvironment provides the minimal environment variables used across all
@ -394,10 +393,10 @@ func (c *CLI) NewDockerComposeCmd(t testing.TB, args ...string) icmd.Cmd {
func ComposeStandalonePath(t testing.TB) string {
t.Helper()
if !composeStandaloneMode {
require.Fail(t, "Not running in standalone mode")
t.Fatal("Not running in standalone mode")
}
composeBinary, err := findExecutable(DockerComposeExecutableName)
require.NoError(t, err, "Could not find standalone Compose binary (%q)",
assert.NilError(t, err, "Could not find standalone Compose binary (%q)",
DockerComposeExecutableName)
return composeBinary
}

View file

@ -24,6 +24,7 @@ import (
"time"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
"gotest.tools/v3/icmd"
)
@ -100,7 +101,7 @@ func TestNetworkLinks(t *testing.T) {
t.Run("curl links in default bridge network", func(t *testing.T) {
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/network-links/compose.yaml", "--project-name", projectName,
"exec", "-T", "container2", "curl", "http://container1/")
assert.Assert(t, strings.Contains(res.Stdout(), "Welcome to nginx!"), res.Stdout())
assert.Assert(t, is.Contains(res.Stdout(), "Welcome to nginx!"))
})
t.Run("down", func(t *testing.T) {

View file

@ -26,7 +26,7 @@ import (
"testing"
"time"
"github.com/stretchr/testify/require"
"gotest.tools/v3/assert"
"gotest.tools/v3/icmd"
)
@ -61,10 +61,11 @@ func TestPause(t *testing.T) {
if resp != nil {
_ = resp.Body.Close()
}
require.Error(t, err, "a should no longer respond")
assert.Assert(t, err != nil, "a should no longer respond")
var netErr net.Error
assert.ErrorType(t, err, &netErr, "expected a network error")
errors.As(err, &netErr)
require.True(t, netErr.Timeout(), "Error should have indicated a timeout")
assert.Assert(t, netErr.Timeout(), "Error should have indicated a timeout")
HTTPGetWithRetry(t, urls["b"], http.StatusOK, 50*time.Millisecond, 5*time.Second)
// unpause a and verify that both containers work again
@ -147,14 +148,16 @@ func publishedPortForService(t testing.TB, cli *CLI, service string, targetPort
PublishedPort int
}
}
require.NoError(t, json.Unmarshal([]byte(res.Stdout()), &svc),
assert.NilError(t, json.Unmarshal([]byte(res.Stdout()), &svc),
"Failed to parse `%s` output", res.Cmd.String())
var found bool
var port int
for _, pp := range svc.Publishers {
if pp.TargetPort == targetPort {
return pp.PublishedPort
found = true
port = pp.PublishedPort
}
}
require.Failf(t, "No published port for target port",
"Target port: %d\nService: %s", targetPort, res.Combined())
return -1
assert.Assert(t, found, "No published port for target port %d\nService: %s", targetPort, res.Combined())
return port
}

View file

@ -21,8 +21,8 @@ import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
"gotest.tools/v3/icmd"
"github.com/docker/compose/v5/pkg/api"
@ -33,25 +33,25 @@ func TestPs(t *testing.T) {
const projectName = "e2e-ps"
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/ps-test/compose.yaml", "--project-name", projectName, "up", "-d")
require.NoError(t, res.Error)
assert.NilError(t, res.Error)
t.Cleanup(func() {
_ = c.RunDockerComposeCmd(t, "--project-name", projectName, "down")
})
assert.Contains(t, res.Combined(), "Container e2e-ps-busybox-1 Started", res.Combined())
assert.Assert(t, is.Contains(res.Combined(), "Container e2e-ps-busybox-1 Started"))
t.Run("table", func(t *testing.T) {
res = c.RunDockerComposeCmd(t, "-f", "./fixtures/ps-test/compose.yaml", "--project-name", projectName, "ps")
lines := strings.Split(res.Stdout(), "\n")
assert.Len(t, lines, 4)
assert.Assert(t, is.Len(lines, 4))
count := 0
for _, line := range lines[1:3] {
if strings.Contains(line, "e2e-ps-busybox-1") {
assert.Contains(t, line, "127.0.0.1:8001->8000/tcp")
assert.Assert(t, is.Contains(line, "127.0.0.1:8001->8000/tcp"))
count++
}
if strings.Contains(line, "e2e-ps-nginx-1") {
assert.Contains(t, line, "80/tcp, 443/tcp, 8080/tcp")
assert.Assert(t, is.Contains(line, "80/tcp, 443/tcp, 8080/tcp"))
count++
}
}
@ -71,18 +71,18 @@ func TestPs(t *testing.T) {
dec := json.NewDecoder(strings.NewReader(out))
for dec.More() {
var s element
require.NoError(t, dec.Decode(&s), "Failed to unmarshal ps JSON output")
assert.NilError(t, dec.Decode(&s), "Failed to unmarshal ps JSON output")
output = append(output, s)
}
count := 0
assert.Len(t, output, 2)
assert.Assert(t, is.Len(output, 2))
for _, service := range output {
assert.Equal(t, projectName, service.Project)
publishers := service.Publishers
if service.Name == "e2e-ps-busybox-1" {
assert.Len(t, publishers, 1)
assert.Equal(t, api.PortPublishers{
assert.Assert(t, is.Len(publishers, 1))
assert.DeepEqual(t, api.PortPublishers{
{
URL: "127.0.0.1",
TargetPort: 8000,
@ -93,8 +93,8 @@ func TestPs(t *testing.T) {
count++
}
if service.Name == "e2e-ps-nginx-1" {
assert.Len(t, publishers, 3)
assert.Equal(t, api.PortPublishers{
assert.Assert(t, is.Len(publishers, 3))
assert.DeepEqual(t, api.PortPublishers{
{TargetPort: 80, Protocol: "tcp"},
{TargetPort: 443, Protocol: "tcp"},
{TargetPort: 8080, Protocol: "tcp"},
@ -108,20 +108,20 @@ func TestPs(t *testing.T) {
t.Run("ps --all", func(t *testing.T) {
res := c.RunDockerComposeCmd(t, "--project-name", projectName, "stop")
require.NoError(t, res.Error)
assert.NilError(t, res.Error)
res = c.RunDockerComposeCmd(t, "-f", "./fixtures/ps-test/compose.yaml", "--project-name", projectName, "ps")
lines := strings.Split(res.Stdout(), "\n")
assert.Len(t, lines, 2)
assert.Assert(t, is.Len(lines, 2))
res = c.RunDockerComposeCmd(t, "-f", "./fixtures/ps-test/compose.yaml", "--project-name", projectName, "ps", "--all")
lines = strings.Split(res.Stdout(), "\n")
assert.Len(t, lines, 4)
assert.Assert(t, is.Len(lines, 4))
})
t.Run("ps unknown", func(t *testing.T) {
res := c.RunDockerComposeCmd(t, "--project-name", projectName, "stop")
require.NoError(t, res.Error)
assert.NilError(t, res.Error)
res = c.RunDockerComposeCmd(t, "-f", "./fixtures/ps-test/compose.yaml", "--project-name", projectName, "ps", "nginx")
res.Assert(t, icmd.Success)

View file

@ -22,15 +22,15 @@ import (
"testing"
"time"
testify "github.com/stretchr/testify/assert"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
)
func assertServiceStatus(t *testing.T, projectName, service, status string, ps string) {
// match output with random spaces like:
// e2e-start-stop-db-1 alpine:latest "echo hello" db 1 minutes ago Exited (0) 1 minutes ago
regx := fmt.Sprintf("%s-%s-1.+%s\\s+.+%s.+", projectName, service, service, status)
testify.Regexp(t, regx, ps)
assert.Assert(t, is.Regexp(regx, ps))
}
func TestRestart(t *testing.T) {

View file

@ -20,7 +20,6 @@ import (
"strings"
"testing"
testify "github.com/stretchr/testify/assert"
"gotest.tools/v3/assert"
"gotest.tools/v3/icmd"
)
@ -182,7 +181,7 @@ func checkServiceContainer(t *testing.T, stdout, containerName, containerState s
if containerState != "" {
errMessage += fmt.Sprintf(" with expected state %s", containerState)
}
testify.Fail(t, errMessage, stdout)
t.Fatalf("%s\n%s", errMessage, stdout)
}
func TestScaleDownNoRecreate(t *testing.T) {

View file

@ -21,8 +21,8 @@ import (
"strings"
"testing"
testify "github.com/stretchr/testify/assert"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
"gotest.tools/v3/icmd"
)
@ -42,7 +42,7 @@ func TestStartStop(t *testing.T) {
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-no-dependencies-simple-1 Started"), res.Combined())
res = c.RunDockerComposeCmd(t, "ls", "--all")
testify.Regexp(t, getProjectRegx("running"), res.Stdout())
assert.Assert(t, is.Regexp(getProjectRegx("running"), res.Stdout()))
res = c.RunDockerComposeCmd(t, "--project-name", projectName, "ps")
assertServiceStatus(t, projectName, "simple", "Up", res.Stdout())
@ -56,7 +56,7 @@ func TestStartStop(t *testing.T) {
assert.Assert(t, !strings.Contains(res.Combined(), "e2e-start-stop-no-dependencies"), res.Combined())
res = c.RunDockerComposeCmd(t, "ls", "--all")
testify.Regexp(t, getProjectRegx("exited"), res.Stdout())
assert.Assert(t, is.Regexp(getProjectRegx("exited"), res.Stdout()))
res = c.RunDockerComposeCmd(t, "--project-name", projectName, "ps")
assert.Assert(t, !strings.Contains(res.Combined(), "e2e-start-stop-no-dependencies-words-1"), res.Combined())
@ -70,7 +70,7 @@ func TestStartStop(t *testing.T) {
c.RunDockerComposeCmd(t, "-f", "./fixtures/start-stop/compose.yaml", "--project-name", projectName, "start")
res := c.RunDockerComposeCmd(t, "ls")
testify.Regexp(t, getProjectRegx("running"), res.Stdout())
assert.Assert(t, is.Regexp(getProjectRegx("running"), res.Stdout()))
})
t.Run("down", func(t *testing.T) {

View file

@ -28,7 +28,6 @@ import (
"testing"
"time"
"github.com/stretchr/testify/require"
"gotest.tools/v3/assert"
"gotest.tools/v3/icmd"
@ -87,7 +86,7 @@ func TestUpDependenciesNotStopped(t *testing.T) {
RequireServiceState(t, c, "dependency", "running")
t.Log("Simulating Ctrl-C")
require.NoError(t, syscall.Kill(-cmd.Process.Pid, syscall.SIGINT),
assert.NilError(t, syscall.Kill(-cmd.Process.Pid, syscall.SIGINT),
"Failed to send SIGINT to compose up process")
t.Log("Waiting for `compose up` to exit")
@ -98,7 +97,7 @@ func TestUpDependenciesNotStopped(t *testing.T) {
if exitErr.ExitCode() == -1 {
t.Fatalf("`compose up` was killed: %v", err)
}
require.Equal(t, 130, exitErr.ExitCode())
assert.Equal(t, 130, exitErr.ExitCode())
}
RequireServiceState(t, c, "app", "exited")

View file

@ -27,7 +27,6 @@ import (
"testing"
"time"
"github.com/stretchr/testify/require"
"gotest.tools/v3/assert"
"gotest.tools/v3/assert/cmp"
"gotest.tools/v3/icmd"
@ -81,7 +80,7 @@ func TestRebuildOnDotEnvWithExternalNetwork(t *testing.T) {
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
r := icmd.StartCmd(cmd)
require.NoError(t, r.Error)
assert.NilError(t, r.Error)
var testComplete atomic.Bool
go func() {
// if the process exits abnormally before the test is done, fail the test
@ -141,9 +140,9 @@ func doTest(t *testing.T, svcName string) {
writeTestFile := func(name, contents, sourceDir string) {
t.Helper()
dest := filepath.Join(sourceDir, name)
require.NoError(t, os.MkdirAll(filepath.Dir(dest), 0o700))
assert.NilError(t, os.MkdirAll(filepath.Dir(dest), 0o700))
t.Logf("writing %q to %q", contents, dest)
require.NoError(t, os.WriteFile(dest, []byte(contents+"\n"), 0o600))
assert.NilError(t, os.WriteFile(dest, []byte(contents+"\n"), 0o600))
}
writeDataFile := func(name, contents string) {
writeTestFile(name, contents, dataDir)
@ -168,7 +167,7 @@ func doTest(t *testing.T, svcName string) {
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
r := icmd.StartCmd(cmd)
require.NoError(t, r.Error)
assert.NilError(t, r.Error)
t.Cleanup(func() {
// IMPORTANT: watch doesn't exit on its own, don't leak processes!
if r.Cmd.Process != nil {
@ -184,7 +183,7 @@ func doTest(t *testing.T, svcName string) {
}
}()
require.NoError(t, os.Mkdir(dataDir, 0o700))
assert.NilError(t, os.Mkdir(dataDir, 0o700))
checkFileContents := func(path string, contents string) poll.Check {
return func(pollLog poll.LogT) poll.Result {
@ -218,7 +217,7 @@ func doTest(t *testing.T, svcName string) {
poll.WaitOn(t, checkFileContents("/app/data/hello.txt", "hello watch"))
t.Logf("Deleting file")
require.NoError(t, os.Remove(filepath.Join(dataDir, "hello.txt")))
assert.NilError(t, os.Remove(filepath.Join(dataDir, "hello.txt")))
waitForFlush()
cli.RunDockerComposeCmdNoCheck(t, "exec", svcName, "stat", "/app/data/hello.txt").
Assert(t, icmd.Expected{
@ -242,7 +241,7 @@ func doTest(t *testing.T, svcName string) {
})
t.Logf("Creating subdirectory")
require.NoError(t, os.Mkdir(filepath.Join(dataDir, "subdir"), 0o700))
assert.NilError(t, os.Mkdir(filepath.Join(dataDir, "subdir"), 0o700))
waitForFlush()
cli.RunDockerComposeCmd(t, "exec", svcName, "stat", "/app/data/subdir")
@ -261,7 +260,7 @@ func doTest(t *testing.T, svcName string) {
poll.WaitOn(t, checkFileContents("/app/data/subdir/file.txt", "x"))
t.Logf("Deleting directory")
require.NoError(t, os.RemoveAll(filepath.Join(dataDir, "subdir")))
assert.NilError(t, os.RemoveAll(filepath.Join(dataDir, "subdir")))
waitForFlush()
cli.RunDockerComposeCmdNoCheck(t, "exec", svcName, "stat", "/app/data/subdir").
Assert(t, icmd.Expected{
@ -270,7 +269,7 @@ func doTest(t *testing.T, svcName string) {
})
t.Logf("Sync and restart use case")
require.NoError(t, os.Mkdir(configDir, 0o700))
assert.NilError(t, os.Mkdir(configDir, 0o700))
writeTestFile("file.config", "This is an updated config file", configDir)
checkRestart := func(state string) poll.Check {
return func(pollLog poll.LogT) poll.Result {
@ -311,7 +310,7 @@ func TestWatchExec(t *testing.T) {
t.Logf("Create new file")
testFile := filepath.Join(tmpdir, "test")
require.NoError(t, os.WriteFile(testFile, []byte("test\n"), 0o600))
assert.NilError(t, os.WriteFile(testFile, []byte("test\n"), 0o600))
poll.WaitOn(t, func(l poll.LogT) poll.Result {
out := buffer.String()
@ -334,7 +333,7 @@ func TestWatchMultiServices(t *testing.T) {
CopyFile(t, filepath.Join("fixtures", "watch", "rebuild.yaml"), composeFilePath)
testFile := filepath.Join(tmpdir, "test")
require.NoError(t, os.WriteFile(testFile, []byte("test"), 0o600))
assert.NilError(t, os.WriteFile(testFile, []byte("test"), 0o600))
cmd := c.NewDockerComposeCmd(t, "-p", projectName, "-f", composeFilePath, "up", "--watch")
buffer := bytes.NewBuffer(nil)
@ -361,7 +360,7 @@ func TestWatchMultiServices(t *testing.T) {
waitRebuild("b", "test")
waitRebuild("c", "test")
require.NoError(t, os.WriteFile(testFile, []byte("updated"), 0o600))
assert.NilError(t, os.WriteFile(testFile, []byte("updated"), 0o600))
waitRebuild("a", "updated")
waitRebuild("b", "updated")
waitRebuild("c", "updated")
@ -391,8 +390,8 @@ func TestWatchIncludes(t *testing.T) {
return poll.Continue("%v", watch.Stdout())
})
require.NoError(t, os.WriteFile(filepath.Join(tmpdir, "B.test"), []byte("test"), 0o600))
require.NoError(t, os.WriteFile(filepath.Join(tmpdir, "A.test"), []byte("test"), 0o600))
assert.NilError(t, os.WriteFile(filepath.Join(tmpdir, "B.test"), []byte("test"), 0o600))
assert.NilError(t, os.WriteFile(filepath.Join(tmpdir, "A.test"), []byte("test"), 0o600))
poll.WaitOn(t, func(l poll.LogT) poll.Result {
cat := c.RunDockerComposeCmdNoCheck(t, "-p", projectName, "exec", "a", "ls", "/data/")

View file

@ -18,12 +18,13 @@ package utils
import (
"bytes"
"fmt"
"strings"
"sync"
"testing"
"time"
"github.com/stretchr/testify/require"
"gotest.tools/v3/poll"
)
// SafeBuffer is a thread safe version of bytes.Buffer
@ -64,15 +65,21 @@ func (b *SafeBuffer) Bytes() []byte {
func (b *SafeBuffer) RequireEventuallyContains(t testing.TB, v string) {
t.Helper()
var bufContents strings.Builder
require.Eventuallyf(t, func() bool {
poll.WaitOn(t, func(logt poll.LogT) poll.Result {
bufContents.Reset()
b.m.Lock()
defer b.m.Unlock()
if _, err := b.b.WriteTo(&bufContents); err != nil {
require.FailNowf(t, "Failed to copy from buffer",
"Error: %v", err)
return poll.Error(fmt.Errorf("failed to copy from buffer. Error: %w", err))
}
return strings.Contains(bufContents.String(), v)
}, 2*time.Second, 20*time.Millisecond,
"Buffer did not contain %q\n============\n%s\n============",
v, &bufContents)
if !strings.Contains(bufContents.String(), v) {
return poll.Continue(
"buffer does not contain %q\n============\n%s\n============",
v, &bufContents)
}
return poll.Success()
},
poll.WithTimeout(2*time.Second),
poll.WithDelay(20*time.Millisecond),
)
}

View file

@ -15,27 +15,34 @@
package utils
import (
"slices"
"testing"
"github.com/stretchr/testify/require"
"gotest.tools/v3/assert"
)
func TestSet_Has(t *testing.T) {
x := NewSet[string]("value")
require.True(t, x.Has("value"))
require.False(t, x.Has("VALUE"))
assert.Check(t, x.Has("value"))
assert.Check(t, !x.Has("VALUE"))
}
func TestSet_Diff(t *testing.T) {
a := NewSet[int](1, 2)
b := NewSet[int](2, 3)
require.ElementsMatch(t, []int{1}, a.Diff(b).Elements())
require.ElementsMatch(t, []int{3}, b.Diff(a).Elements())
assert.DeepEqual(t, []int{1}, a.Diff(b).Elements())
assert.DeepEqual(t, []int{3}, b.Diff(a).Elements())
}
func TestSet_Union(t *testing.T) {
a := NewSet[int](1, 2)
b := NewSet[int](2, 3)
require.ElementsMatch(t, []int{1, 2, 3}, a.Union(b).Elements())
require.ElementsMatch(t, []int{1, 2, 3}, b.Union(a).Elements())
actual := a.Union(b).Elements()
slices.Sort(actual)
assert.DeepEqual(t, []int{1, 2, 3}, actual)
actual = b.Union(a).Elements()
slices.Sort(actual)
assert.DeepEqual(t, []int{1, 2, 3}, actual)
}

View file

@ -18,8 +18,7 @@ package watch_test
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gotest.tools/v3/assert"
"github.com/docker/compose/v5/pkg/watch"
)
@ -37,12 +36,12 @@ func TestEphemeralPathMatcher(t *testing.T) {
matcher := watch.EphemeralPathMatcher()
for _, p := range ignored {
ok, err := matcher.Matches(p)
require.NoErrorf(t, err, "Matching %s", p)
assert.Truef(t, ok, "Path %s should have matched", p)
assert.NilError(t, err, "Matching %s", p)
assert.Assert(t, ok, "Path %s should have matched", p)
}
const includedPath = "normal.txt"
ok, err := matcher.Matches(includedPath)
require.NoErrorf(t, err, "Matching %s", includedPath)
assert.Falsef(t, ok, "Path %s should NOT have matched", includedPath)
assert.NilError(t, err, "Matching %s", includedPath)
assert.Assert(t, !ok, "Path %s should NOT have matched", includedPath)
}

View file

@ -27,8 +27,7 @@ import (
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gotest.tools/v3/assert"
)
// Each implementation of the notify interface should have the same basic
@ -126,7 +125,7 @@ func TestGitBranchSwitch(t *testing.T) {
if i != 0 {
err := os.RemoveAll(dir)
require.NoError(t, err)
assert.NilError(t, err)
}
}
@ -149,7 +148,7 @@ func TestGitBranchSwitch(t *testing.T) {
f.assertEvents(path)
// Make sure there are no errors in the out stream
assert.Empty(t, f.out.String())
assert.Assert(t, f.out.String() == "")
}
func TestWatchesAreRecursive(t *testing.T) {
@ -357,7 +356,7 @@ func TestWatchBrokenLink(t *testing.T) {
f.watch(newRoot.Path())
err = os.Remove(link)
require.NoError(t, err)
assert.NilError(t, err)
f.assertEvents(link)
}

View file

@ -20,25 +20,24 @@ import (
"runtime"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gotest.tools/v3/assert"
)
func TestGreatestExistingAncestor(t *testing.T) {
f := NewTempDirFixture(t)
p, err := greatestExistingAncestor(f.Path())
require.NoError(t, err)
assert.NilError(t, err)
assert.Equal(t, f.Path(), p)
p, err = greatestExistingAncestor(f.JoinPath("missing"))
require.NoError(t, err)
assert.NilError(t, err)
assert.Equal(t, f.Path(), p)
missingTopLevel := "/missingDir/a/b/c"
if runtime.GOOS == "windows" {
missingTopLevel = "C:\\missingDir\\a\\b\\c"
missingTopLevel = `C:\missingDir\a\b\c`
}
_, err = greatestExistingAncestor(missingTopLevel)
assert.Contains(t, err.Error(), "cannot watch root directory")
assert.ErrorContains(t, err, "cannot watch root directory")
}

View file

@ -26,7 +26,7 @@ import (
"strings"
"testing"
"github.com/stretchr/testify/require"
"gotest.tools/v3/assert"
)
func TestDontWatchEachFile(t *testing.T) {
@ -113,7 +113,7 @@ func TestDontWatchEachFile(t *testing.T) {
f.events = nil
n, err := inotifyNodes()
require.NoError(t, err)
assert.NilError(t, err)
if n > 10 {
t.Fatalf("watching more than 10 files: %d", n)
}
@ -152,7 +152,7 @@ func TestDontRecurseWhenWatchingParentsOfNonExistentFiles(t *testing.T) {
f.fsync()
n, err := inotifyNodes()
require.NoError(t, err)
assert.NilError(t, err)
if n > 5 {
t.Fatalf("watching more than 5 files: %d", n)
}