Przeglądaj źródła

Add a CliSuite for cli unit tests

Makes writing unit tests for commands quite easier
Djordje Lukic 5 lat temu
rodzic
commit
8495500aa2

+ 2 - 2
Dockerfile

@@ -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}

+ 4 - 57
cli/cmd/context/ls_test.go

@@ -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) {

+ 8 - 62
cli/cmd/ps_test.go

@@ -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) {

+ 3 - 7
context/store/store.go

@@ -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
 	}

+ 1 - 1
context/store/storedefault.go

@@ -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

+ 1 - 1
context/store/storedefault_test.go

@@ -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)
 }

+ 77 - 0
tests/framework/clisuite.go

@@ -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)
+}