# README
Deck
Make testing easier and under control and every package more reliable!
Usages
os.Exit
Use var osExit = deck.OsExit
to replace os.Exit
.
import (
"github.com/go-dawn/pkg/deck"
"github.com/stretchr/testify/assert"
)
var osExit = deck.OsExit
func TestSomeFunction(t *testing.T) {
var count int32
deck.SetupOsExit(func(code int) {
atomic.AddInt32(&count, int32(code))
})
defer deck.TeardownOsExit()
SomeFunction()
assert.Equal(t, int32(100), atomic.LoadInt32(&count))
}
func SomeFunction() {
osExit(100)
}
exec.Command
Use var execCommand = deck.ExecCommand
to replace exec.Command
. And the TestHelperCommand
test function must be added in one of the test file in the package. You must use deck.HandleCommand
function and determine the output of the executed command.
import (
"github.com/go-dawn/pkg/deck"
"github.com/stretchr/testify/assert"
)
var execCommand = deck.ExecCommand
func TestSomeFunction(t *testing.T) {
at := assert.New(t)
t.Run("success", func(t *testing.T) {
deck.SetupCmd()
defer deck.TeardownCmd()
b, err := SomeFunction()
at.Nil(err)
at.Equal("[test function]", string(b))
})
t.Run("error", func(t *testing.T) {
deck.SetupCmdError()
defer deck.TeardownCmd()
b, err := SomeFunction()
at.NotNil(err)
at.Equal("", string(b))
})
t.Run("stderr", func(t *testing.T) {
deck.SetupCmdStderr()
defer deck.TeardownCmd()
b, err := SomeFunction()
at.NotNil(err)
at.Equal("[test function]", string(b))
})
}
func TestHelperCommand(t *testing.T) {
deck.HandleCommand(func(args []string, expectStderr bool) {
if expectStderr {
_, _ = fmt.Fprintf(os.Stderr, "%v", args)
os.Exit(1)
}
_, _ = fmt.Fprintf(os.Stdout, "%v", args)
})
}
func SomeFunction() ([]byte, error) {
cmd := execCommand("test", "function")
return cmd.CombinedOutput()
}
exec.LookPath
Use var execLookPath = deck.ExecLookPath
to replace exec.LookPath
.
import (
"github.com/go-dawn/pkg/deck"
"github.com/stretchr/testify/assert"
)
var execLookPath = deck.ExecLookPath
func TestSomeFunction(t *testing.T) {
at := assert.New(t)
t.Run("success", func(t *testing.T) {
SetupExecLookPath()
defer TeardownExecLookPath()
bin, err := SomeFunction()
at.Nil(err)
at.Equal("test", bin)
})
t.Run("error", func(t *testing.T) {
SetupExecLookPathError()
defer TeardownExecLookPath()
bin, err := SomeFunction()
at.Equal(ErrLookPath, err)
at.Equal("", bin)
})
}
func SomeFunction() (string, error) {
return execLookPath("test")
}
os.Stdout
Use var stdout = deck.Stdout
to replace os.Stdout
.
import (
"github.com/go-dawn/pkg/deck"
"github.com/stretchr/testify/assert"
)
var stdout = deck.Stdout
func TestSomeFunction(t *testing.T) {
at := assert.New(t)
deck.RedirectStdout()
SomeFunction()
output := deck.DumpStdout()
at.Equal("stdout", output)
}
func SomeFunction() {
_, _ = fmt.Fprint(stdout, "stdout")
}
os.Stderr
Use var stderr = deck.Stderr
to replace os.Stderr
.
import (
"github.com/go-dawn/pkg/deck"
"github.com/stretchr/testify/assert"
)
var stderr = deck.Stderr
func TestSomeFunction(t *testing.T) {
at := assert.New(t)
deck.RedirectStderr()
SomeFunction()
output := deck.DumpStderr()
at.Equal("stderr", output)
}
func SomeFunction() {
_, _ = fmt.Fprint(stderr, "stderr")
}
os.Environment
We can override or set environment and restore them back during testing.
import (
"github.com/go-dawn/pkg/deck"
"github.com/stretchr/testify/assert"
)
func TestSomeFunction(t *testing.T) {
at := assert.New(t)
key1 := "DAWN_DECK"
key2 := "DAWN_DECK2"
oldValue := "1"
newValue := "2"
at.Nil(os.Setenv(key1, oldValue))
deck.SetupEnvs(deck.Envs{key1: newValue, key2: newValue})
v1, v2 := SomeFunction(key1, key2)
at.Equal(newValue, v1)
at.Equal(newValue, v2)
deck.TeardownEnvs()
at.Equal(oldValue, os.Getenv(key1))
at.Equal("", os.Getenv(key2))
}
func SomeFunction(k1, k2 string) (string, string){
return os.Getenv(k1), os.Getenv(k2)
}
cobra.Command
Use RunCobraCmd
to test a cobra command.
import (
"github.com/go-dawn/pkg/deck"
"github.com/stretchr/testify/assert"
)
func TestRunCobraCmd(t *testing.T) {
at := assert.New(t)
cmd := &cobra.Command{
Use: "test",
Run: func(cmd *cobra.Command, args []string) {
cmd.Printf("%v", args)
},
}
out, err := deck.RunCobraCmd(cmd, "cobra")
at.Nil(err)
at.Equal("[cobra]", out)
}
httptest
Use SetupServer
to register fiber routes and get an *httptest.Expect
instance as e
. Next make request by e
and finally do assertion with several helper functions.
import (
"testing"
"github.com/gavv/httpexpect/v2"
"github.com/go-dawn/dawn/fiberx"
"github.com/go-dawn/pkg/deck"
"github.com/gofiber/fiber/v2"
)
func Test_Fiber_Routes(t *testing.T) {
e := deck.SetupServer(t, func(app *fiber.App) {
app.Get("/", func(c *fiber.Ctx) error {
return fiberx.Message(c, "test")
})
})
resp := e.GET("/").Expect()
deck.AssertRespStatus(resp, fiber.StatusOK)
deck.AssertRespCode(resp, 200)
deck.AssertRespMsg(resp, "test")
deck.AssertRespMsgContains(resp, "es")
data := deck.Expected{
Status: 500,
Code: 500,
Msg: "error",
Contain: false,
}
e = deck.SetupServer(t, func(app *fiber.App) {
app.Get("/data", func(c *fiber.Ctx) error {
return fiberx.Data(c, data)
})
})
resp2 := e.GET("/data").Expect()
deck.AssertRespData(resp2, data)
deck.AssertRespDataCheck(resp2, func(v *httpexpect.Value) {
obj := v.Object()
obj.ValueEqual("Status", 500)
obj.ValueEqual("Code", 500)
obj.ValueEqual("Msg", "error")
obj.ValueEqual("Contain", false)
})
}
gorm
Use SetupGormDB
to get a *gorm.DB
instance as gdb
and passed in models will be auto migrated. gdb
is driven by an in-memory sqlite
db.
import (
"testing"
"github.com/go-dawn/pkg/deck"
"github.com/stretchr/testify/assert"
"gorm.io/gorm"
)
type Fake struct {
gorm.Model
F string
}
func Test_DryRunSession(t *testing.T) {
s := deck.DryRunSession(t)
stat := s.Find(&Fake{}).Statement
assert.Equal(t, "SELECT * FROM `fakes` WHERE `fakes`.`deleted_at` IS NULL", stat.SQL.String())
}
func Test_AssertDBCount(t *testing.T) {
gdb := deck.SetupGormDB(t, &Fake{})
deck.AssertDBCount(t, gdb.Model(&Fake{}), int64(0))
}
func Test_AssertDBHas(t *testing.T) {
gdb := deck.SetupGormDB(t, &Fake{})
assert.Nil(t, gdb.Create(&Fake{F: "f"}).Error)
deck.AssertDBHas(t, gdb.Model(&Fake{}), Columns{"F": "f"})
}
func Test_AssertDBMissing(t *testing.T) {
gdb := deck.SetupGormDB(t, &Fake{})
deck.AssertDBMissing(t, gdb.Model(&Fake{}), Columns{"F": "f"})
}