mirror of https://github.com/docker/compose.git
Add a CliSuite for cli unit tests
Makes writing unit tests for commands quite easier
This commit is contained in:
parent
fe36c49246
commit
8495500aa2
|
@ -1,5 +1,5 @@
|
|||
# syntax = docker/dockerfile:experimental
|
||||
ARG GO_VERSION=1.14.3-alpine3.11
|
||||
ARG GO_VERSION=1.14.3-alpine
|
||||
|
||||
FROM golang:${GO_VERSION} AS base
|
||||
ARG TARGET_OS=unknown
|
||||
|
@ -7,7 +7,7 @@ ARG TARGET_ARCH=unknown
|
|||
ARG PWD=/api
|
||||
ENV GO111MODULE=on
|
||||
|
||||
RUN apk update && apk add docker make
|
||||
RUN apk update && apk add -U docker make
|
||||
|
||||
WORKDIR ${PWD}
|
||||
ADD go.* ${PWD}
|
||||
|
|
|
@ -1,76 +1,23 @@
|
|||
package context
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"gotest.tools/v3/golden"
|
||||
|
||||
apicontext "github.com/docker/api/context"
|
||||
"github.com/docker/api/context/store"
|
||||
"github.com/docker/api/tests/framework"
|
||||
)
|
||||
|
||||
type ContextSuite struct {
|
||||
suite.Suite
|
||||
ctx context.Context
|
||||
writer *os.File
|
||||
reader *os.File
|
||||
originalStdout *os.File
|
||||
storeRoot string
|
||||
}
|
||||
|
||||
func (sut *ContextSuite) BeforeTest(suiteName, testName string) {
|
||||
ctx := context.Background()
|
||||
ctx = apicontext.WithCurrentContext(ctx, "example")
|
||||
dir, err := ioutil.TempDir("", "store")
|
||||
require.Nil(sut.T(), err)
|
||||
s, err := store.New(
|
||||
store.WithRoot(dir),
|
||||
)
|
||||
require.Nil(sut.T(), err)
|
||||
|
||||
err = s.Create("example", store.TypedContext{
|
||||
Type: "example",
|
||||
})
|
||||
require.Nil(sut.T(), err)
|
||||
|
||||
sut.storeRoot = dir
|
||||
|
||||
ctx = store.WithContextStore(ctx, s)
|
||||
sut.ctx = ctx
|
||||
|
||||
sut.originalStdout = os.Stdout
|
||||
r, w, err := os.Pipe()
|
||||
require.Nil(sut.T(), err)
|
||||
|
||||
os.Stdout = w
|
||||
sut.writer = w
|
||||
sut.reader = r
|
||||
}
|
||||
|
||||
func (sut *ContextSuite) getStdOut() string {
|
||||
err := sut.writer.Close()
|
||||
require.Nil(sut.T(), err)
|
||||
|
||||
out, _ := ioutil.ReadAll(sut.reader)
|
||||
|
||||
return string(out)
|
||||
}
|
||||
|
||||
func (sut *ContextSuite) AfterTest(suiteName, testName string) {
|
||||
os.Stdout = sut.originalStdout
|
||||
err := os.RemoveAll(sut.storeRoot)
|
||||
require.Nil(sut.T(), err)
|
||||
framework.CliSuite
|
||||
}
|
||||
|
||||
func (sut *ContextSuite) TestLs() {
|
||||
err := runList(sut.ctx)
|
||||
err := runList(sut.Context())
|
||||
require.Nil(sut.T(), err)
|
||||
golden.Assert(sut.T(), sut.getStdOut(), "ls-out.golden")
|
||||
golden.Assert(sut.T(), sut.GetStdOut(), "ls-out.golden")
|
||||
}
|
||||
|
||||
func TestPs(t *testing.T) {
|
||||
|
|
|
@ -1,72 +1,18 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"gotest.tools/v3/golden"
|
||||
|
||||
apicontext "github.com/docker/api/context"
|
||||
"github.com/docker/api/context/store"
|
||||
_ "github.com/docker/api/example"
|
||||
"github.com/docker/api/tests/framework"
|
||||
)
|
||||
|
||||
type PsSuite struct {
|
||||
suite.Suite
|
||||
ctx context.Context
|
||||
writer *os.File
|
||||
reader *os.File
|
||||
originalStdout *os.File
|
||||
storeRoot string
|
||||
}
|
||||
|
||||
func (sut *PsSuite) BeforeTest(suiteName, testName string) {
|
||||
ctx := context.Background()
|
||||
ctx = apicontext.WithCurrentContext(ctx, "example")
|
||||
dir, err := ioutil.TempDir("", "store")
|
||||
require.Nil(sut.T(), err)
|
||||
s, err := store.New(
|
||||
store.WithRoot(dir),
|
||||
)
|
||||
require.Nil(sut.T(), err)
|
||||
|
||||
err = s.Create("example", store.TypedContext{
|
||||
Type: "example",
|
||||
})
|
||||
require.Nil(sut.T(), err)
|
||||
|
||||
sut.storeRoot = dir
|
||||
|
||||
ctx = store.WithContextStore(ctx, s)
|
||||
sut.ctx = ctx
|
||||
|
||||
sut.originalStdout = os.Stdout
|
||||
r, w, err := os.Pipe()
|
||||
require.Nil(sut.T(), err)
|
||||
|
||||
os.Stdout = w
|
||||
sut.writer = w
|
||||
sut.reader = r
|
||||
}
|
||||
|
||||
func (sut *PsSuite) getStdOut() string {
|
||||
err := sut.writer.Close()
|
||||
require.Nil(sut.T(), err)
|
||||
|
||||
out, _ := ioutil.ReadAll(sut.reader)
|
||||
|
||||
return string(out)
|
||||
}
|
||||
|
||||
func (sut *PsSuite) AfterTest(suiteName, testName string) {
|
||||
os.Stdout = sut.originalStdout
|
||||
err := os.RemoveAll(sut.storeRoot)
|
||||
require.Nil(sut.T(), err)
|
||||
framework.CliSuite
|
||||
}
|
||||
|
||||
func (sut *PsSuite) TestPs() {
|
||||
|
@ -74,10 +20,10 @@ func (sut *PsSuite) TestPs() {
|
|||
quiet: false,
|
||||
}
|
||||
|
||||
err := runPs(sut.ctx, opts)
|
||||
assert.Nil(sut.T(), err)
|
||||
err := runPs(sut.Context(), opts)
|
||||
require.Nil(sut.T(), err)
|
||||
|
||||
golden.Assert(sut.T(), sut.getStdOut(), "ps-out.golden")
|
||||
golden.Assert(sut.T(), sut.GetStdOut(), "ps-out.golden")
|
||||
}
|
||||
|
||||
func (sut *PsSuite) TestPsQuiet() {
|
||||
|
@ -85,10 +31,10 @@ func (sut *PsSuite) TestPsQuiet() {
|
|||
quiet: true,
|
||||
}
|
||||
|
||||
err := runPs(sut.ctx, opts)
|
||||
assert.Nil(sut.T(), err)
|
||||
err := runPs(sut.Context(), opts)
|
||||
require.Nil(sut.T(), err)
|
||||
|
||||
golden.Assert(sut.T(), sut.getStdOut(), "ps-out-quiet.golden")
|
||||
golden.Assert(sut.T(), sut.GetStdOut(), "ps-out-quiet.golden")
|
||||
}
|
||||
|
||||
func TestPs(t *testing.T) {
|
||||
|
|
|
@ -146,12 +146,12 @@ func read(meta string, getter func() interface{}) (*Metadata, error) {
|
|||
}
|
||||
|
||||
var um untypedMetadata
|
||||
if err := marshalTyped(bytes, &um); err != nil {
|
||||
if err := json.Unmarshal(bytes, &um); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var uc untypedContext
|
||||
if err := marshalTyped(um.Metadata, &uc); err != nil {
|
||||
if err := json.Unmarshal(um.Metadata, &uc); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if uc.Type == "" {
|
||||
|
@ -178,10 +178,6 @@ func read(meta string, getter func() interface{}) (*Metadata, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
func marshalTyped(in []byte, val interface{}) error {
|
||||
return json.Unmarshal(in, val)
|
||||
}
|
||||
|
||||
func parse(payload []byte, getter func() interface{}) (interface{}, error) {
|
||||
if getter == nil {
|
||||
var res map[string]interface{}
|
||||
|
@ -266,7 +262,7 @@ func (s *store) List() ([]*Metadata, error) {
|
|||
|
||||
// The default context is not stored in the store, it is in-memory only
|
||||
// so we need a special case for it.
|
||||
dockerDefault, err := dockerGefaultContext()
|
||||
dockerDefault, err := dockerDefaultContext()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ type endpoint struct {
|
|||
DefaultNamespace string
|
||||
}
|
||||
|
||||
func dockerGefaultContext() (*Metadata, error) {
|
||||
func dockerDefaultContext() (*Metadata, error) {
|
||||
cmd := exec.Command("docker", "context", "inspect", "default")
|
||||
var stdout bytes.Buffer
|
||||
cmd.Stdout = &stdout
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
)
|
||||
|
||||
func TestDefaultContext(t *testing.T) {
|
||||
s, err := dockerGefaultContext()
|
||||
s, err := dockerDefaultContext()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "default", s.Name)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
package framework
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
apicontext "github.com/docker/api/context"
|
||||
"github.com/docker/api/context/store"
|
||||
)
|
||||
|
||||
// CliSuite is a helper struct that creates a configured context
|
||||
// and captures the output of a command. it should be used in the
|
||||
// same way as testify.suite.Suite
|
||||
type CliSuite struct {
|
||||
suite.Suite
|
||||
ctx context.Context
|
||||
writer *os.File
|
||||
reader *os.File
|
||||
OriginalStdout *os.File
|
||||
storeRoot string
|
||||
}
|
||||
|
||||
// BeforeTest is called by testify.suite
|
||||
func (sut *CliSuite) BeforeTest(suiteName, testName string) {
|
||||
ctx := context.Background()
|
||||
ctx = apicontext.WithCurrentContext(ctx, "example")
|
||||
dir, err := ioutil.TempDir("", "store")
|
||||
require.Nil(sut.T(), err)
|
||||
s, err := store.New(
|
||||
store.WithRoot(dir),
|
||||
)
|
||||
require.Nil(sut.T(), err)
|
||||
|
||||
err = s.Create("example", store.TypedContext{
|
||||
Type: "example",
|
||||
})
|
||||
require.Nil(sut.T(), err)
|
||||
|
||||
sut.storeRoot = dir
|
||||
|
||||
ctx = store.WithContextStore(ctx, s)
|
||||
sut.ctx = ctx
|
||||
|
||||
sut.OriginalStdout = os.Stdout
|
||||
r, w, err := os.Pipe()
|
||||
require.Nil(sut.T(), err)
|
||||
|
||||
os.Stdout = w
|
||||
sut.writer = w
|
||||
sut.reader = r
|
||||
}
|
||||
|
||||
// Context returns a configured context
|
||||
func (sut *CliSuite) Context() context.Context {
|
||||
return sut.ctx
|
||||
}
|
||||
|
||||
// GetStdOut returns the output of the command
|
||||
func (sut *CliSuite) GetStdOut() string {
|
||||
err := sut.writer.Close()
|
||||
require.Nil(sut.T(), err)
|
||||
|
||||
out, _ := ioutil.ReadAll(sut.reader)
|
||||
|
||||
return string(out)
|
||||
}
|
||||
|
||||
// AfterTest is called by testify.suite
|
||||
func (sut *CliSuite) AfterTest(suiteName, testName string) {
|
||||
os.Stdout = sut.OriginalStdout
|
||||
err := os.RemoveAll(sut.storeRoot)
|
||||
require.Nil(sut.T(), err)
|
||||
}
|
Loading…
Reference in New Issue