mirror of
https://github.com/jimeh/go-mocktesting.git
synced 2026-02-19 03:46:40 +00:00
feat(mocktesting): initial implementation
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
bin/*
|
||||||
|
coverage.out
|
||||||
205
Makefile
Normal file
205
Makefile
Normal file
@@ -0,0 +1,205 @@
|
|||||||
|
GOMODNAME := $(shell grep 'module' go.mod | sed -e 's/^module //')
|
||||||
|
SOURCES := $(shell find . -name "*.go" -or -name "go.mod" -or -name "go.sum" \
|
||||||
|
-or -name "Makefile")
|
||||||
|
|
||||||
|
# Verbose output
|
||||||
|
ifdef VERBOSE
|
||||||
|
V = -v
|
||||||
|
endif
|
||||||
|
|
||||||
|
#
|
||||||
|
# Environment
|
||||||
|
#
|
||||||
|
|
||||||
|
BINDIR := bin
|
||||||
|
TOOLDIR := $(BINDIR)/tools
|
||||||
|
|
||||||
|
# Global environment variables for all targets
|
||||||
|
SHELL ?= /bin/bash
|
||||||
|
SHELL := env \
|
||||||
|
GO111MODULE=on \
|
||||||
|
GOBIN=$(CURDIR)/$(TOOLDIR) \
|
||||||
|
CGO_ENABLED=1 \
|
||||||
|
PATH='$(CURDIR)/$(BINDIR):$(CURDIR)/$(TOOLDIR):$(PATH)' \
|
||||||
|
$(SHELL)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Defaults
|
||||||
|
#
|
||||||
|
|
||||||
|
# Default target
|
||||||
|
.DEFAULT_GOAL := test
|
||||||
|
|
||||||
|
#
|
||||||
|
# Tools
|
||||||
|
#
|
||||||
|
|
||||||
|
TOOLS += $(TOOLDIR)/gobin
|
||||||
|
$(TOOLDIR)/gobin:
|
||||||
|
GO111MODULE=off go get -u github.com/myitcv/gobin
|
||||||
|
|
||||||
|
# external tool
|
||||||
|
define tool # 1: binary-name, 2: go-import-path
|
||||||
|
TOOLS += $(TOOLDIR)/$(1)
|
||||||
|
|
||||||
|
$(TOOLDIR)/$(1): $(TOOLDIR)/gobin Makefile
|
||||||
|
gobin $(V) "$(2)"
|
||||||
|
endef
|
||||||
|
|
||||||
|
$(eval $(call tool,godoc,golang.org/x/tools/cmd/godoc))
|
||||||
|
$(eval $(call tool,gofumpt,mvdan.cc/gofumpt))
|
||||||
|
$(eval $(call tool,goimports,golang.org/x/tools/cmd/goimports))
|
||||||
|
$(eval $(call tool,golangci-lint,github.com/golangci/golangci-lint/cmd/golangci-lint@v1.43))
|
||||||
|
$(eval $(call tool,gomod,github.com/Helcaraxan/gomod))
|
||||||
|
|
||||||
|
.PHONY: tools
|
||||||
|
tools: $(TOOLS)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Development
|
||||||
|
#
|
||||||
|
|
||||||
|
BENCH ?= .
|
||||||
|
TESTARGS ?=
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
rm -f $(TOOLS)
|
||||||
|
rm -f ./coverage.out ./go.mod.tidy-check ./go.sum.tidy-check
|
||||||
|
|
||||||
|
.PHONY: test
|
||||||
|
test:
|
||||||
|
go test $(V) -count=1 -race $(TESTARGS) ./...
|
||||||
|
|
||||||
|
.PHONY: test-deps
|
||||||
|
test-deps:
|
||||||
|
go test all
|
||||||
|
|
||||||
|
.PHONY: lint
|
||||||
|
lint: $(TOOLDIR)/golangci-lint
|
||||||
|
golangci-lint $(V) run
|
||||||
|
|
||||||
|
.PHONY: format
|
||||||
|
format: $(TOOLDIR)/goimports $(TOOLDIR)/gofumpt
|
||||||
|
goimports -w . && gofumpt -w .
|
||||||
|
|
||||||
|
.SILENT: bench
|
||||||
|
.PHONY: bench
|
||||||
|
bench:
|
||||||
|
go test $(V) -count=1 -bench=$(BENCH) $(TESTARGS) ./...
|
||||||
|
|
||||||
|
.PHONY: golden-update
|
||||||
|
golden-update:
|
||||||
|
GOLDEN_UPDATE=1 $(MAKE) test
|
||||||
|
|
||||||
|
.PHONY: golden-clean
|
||||||
|
golden-clean:
|
||||||
|
find . -type f -name '*.golden' -path '*/testdata/*' -delete
|
||||||
|
find . -type d -empty -path '*/testdata/*' -delete
|
||||||
|
|
||||||
|
.PHONY: golden-regen
|
||||||
|
golden-regen: golden-clean golden-update
|
||||||
|
|
||||||
|
#
|
||||||
|
# Code Generation
|
||||||
|
#
|
||||||
|
|
||||||
|
.PHONY: generate
|
||||||
|
generate:
|
||||||
|
go generate ./...
|
||||||
|
|
||||||
|
.PHONY: check-generate
|
||||||
|
check-generate:
|
||||||
|
$(eval CHKDIR := $(shell mktemp -d))
|
||||||
|
cp -av . "$(CHKDIR)"
|
||||||
|
make -C "$(CHKDIR)/" generate
|
||||||
|
( diff -rN . "$(CHKDIR)" && rm -rf "$(CHKDIR)" ) || \
|
||||||
|
( rm -rf "$(CHKDIR)" && exit 1 )
|
||||||
|
|
||||||
|
#
|
||||||
|
# Coverage
|
||||||
|
#
|
||||||
|
|
||||||
|
.PHONY: cov
|
||||||
|
cov: coverage.out
|
||||||
|
|
||||||
|
.PHONY: cov-html
|
||||||
|
cov-html: coverage.out
|
||||||
|
go tool cover -html=./coverage.out
|
||||||
|
|
||||||
|
.PHONY: cov-func
|
||||||
|
cov-func: coverage.out
|
||||||
|
go tool cover -func=./coverage.out
|
||||||
|
|
||||||
|
coverage.out: $(SOURCES)
|
||||||
|
go test $(V) -covermode=count -coverprofile=./coverage.out ./...
|
||||||
|
|
||||||
|
#
|
||||||
|
# Dependencies
|
||||||
|
#
|
||||||
|
|
||||||
|
.PHONY: deps
|
||||||
|
deps:
|
||||||
|
go mod download
|
||||||
|
|
||||||
|
.PHONY: deps-update
|
||||||
|
deps-update:
|
||||||
|
go get -u -t ./...
|
||||||
|
|
||||||
|
.PHONY: deps-analyze
|
||||||
|
deps-analyze: $(TOOLDIR)/gomod
|
||||||
|
gomod analyze
|
||||||
|
|
||||||
|
.PHONY: tidy
|
||||||
|
tidy:
|
||||||
|
go mod tidy $(V)
|
||||||
|
|
||||||
|
.PHONY: verify
|
||||||
|
verify:
|
||||||
|
go mod verify
|
||||||
|
|
||||||
|
.SILENT: check-tidy
|
||||||
|
.PHONY: check-tidy
|
||||||
|
check-tidy:
|
||||||
|
cp go.mod go.mod.tidy-check
|
||||||
|
cp go.sum go.sum.tidy-check
|
||||||
|
go mod tidy
|
||||||
|
( \
|
||||||
|
diff go.mod go.mod.tidy-check && \
|
||||||
|
diff go.sum go.sum.tidy-check && \
|
||||||
|
rm -f go.mod go.sum && \
|
||||||
|
mv go.mod.tidy-check go.mod && \
|
||||||
|
mv go.sum.tidy-check go.sum \
|
||||||
|
) || ( \
|
||||||
|
rm -f go.mod go.sum && \
|
||||||
|
mv go.mod.tidy-check go.mod && \
|
||||||
|
mv go.sum.tidy-check go.sum; \
|
||||||
|
exit 1 \
|
||||||
|
)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Documentation
|
||||||
|
#
|
||||||
|
|
||||||
|
# Serve docs
|
||||||
|
.PHONY: docs
|
||||||
|
docs: $(TOOLDIR)/godoc
|
||||||
|
$(info serviing docs on http://127.0.0.1:6060/pkg/$(GOMODNAME)/)
|
||||||
|
@godoc -http=127.0.0.1:6060
|
||||||
|
|
||||||
|
#
|
||||||
|
# Release
|
||||||
|
#
|
||||||
|
|
||||||
|
.PHONY: new-version
|
||||||
|
new-version: check-npx
|
||||||
|
npx standard-version
|
||||||
|
|
||||||
|
.PHONY: next-version
|
||||||
|
next-version: check-npx
|
||||||
|
npx standard-version --dry-run
|
||||||
|
|
||||||
|
.PHONY: check-npx
|
||||||
|
check-npx:
|
||||||
|
$(if $(shell which npx),,\
|
||||||
|
$(error No npx found in PATH, please install NodeJS))
|
||||||
189
example_test.go
Normal file
189
example_test.go
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
package mocktesting_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/jimeh/go-mocktesting"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Example_basic() {
|
||||||
|
assertTrue := func(t testing.TB, v bool) {
|
||||||
|
if v != true {
|
||||||
|
t.Error("expected false to be true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mt := mocktesting.NewT("TestMyBoolean1")
|
||||||
|
assertTrue(mt, true)
|
||||||
|
fmt.Printf("Name: %s\n", mt.Name())
|
||||||
|
fmt.Printf("Failed: %+v\n", mt.Failed())
|
||||||
|
fmt.Printf("Aborted: %+v\n", mt.Aborted())
|
||||||
|
|
||||||
|
mt = mocktesting.NewT("TestMyBoolean2")
|
||||||
|
assertTrue(mt, false)
|
||||||
|
fmt.Printf("Name: %s\n", mt.Name())
|
||||||
|
fmt.Printf("Failed: %+v\n", mt.Failed())
|
||||||
|
fmt.Printf("Aborted: %+v\n", mt.Aborted())
|
||||||
|
fmt.Printf("Output: %s\n", strings.Join(mt.Output(), ""))
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// Name: TestMyBoolean1
|
||||||
|
// Failed: false
|
||||||
|
// Aborted: false
|
||||||
|
// Name: TestMyBoolean2
|
||||||
|
// Failed: true
|
||||||
|
// Aborted: false
|
||||||
|
// Output: expected false to be true
|
||||||
|
}
|
||||||
|
|
||||||
|
func Example_fatal() {
|
||||||
|
requireTrue := func(t testing.TB, v bool) {
|
||||||
|
if v != true {
|
||||||
|
t.Fatal("expected false to be true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mt := mocktesting.NewT("TestMyBoolean1")
|
||||||
|
requireTrue(mt, true)
|
||||||
|
fmt.Printf("Name: %s\n", mt.Name())
|
||||||
|
fmt.Printf("Failed: %+v\n", mt.Failed())
|
||||||
|
fmt.Printf("Aborted: %+v\n", mt.Aborted())
|
||||||
|
|
||||||
|
mt = mocktesting.NewT("TestMyBoolean2")
|
||||||
|
mocktesting.Go(func() {
|
||||||
|
requireTrue(mt, false)
|
||||||
|
fmt.Println("This is never executed.")
|
||||||
|
})
|
||||||
|
fmt.Printf("Name: %s\n", mt.Name())
|
||||||
|
fmt.Printf("Failed: %+v\n", mt.Failed())
|
||||||
|
fmt.Printf("Aborted: %+v\n", mt.Aborted())
|
||||||
|
fmt.Printf("Output: %s\n", strings.Join(mt.Output(), ""))
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// Name: TestMyBoolean1
|
||||||
|
// Failed: false
|
||||||
|
// Aborted: false
|
||||||
|
// Name: TestMyBoolean2
|
||||||
|
// Failed: true
|
||||||
|
// Aborted: true
|
||||||
|
// Output: expected false to be true
|
||||||
|
}
|
||||||
|
|
||||||
|
func Example_subtests() {
|
||||||
|
requireTrue := func(t testing.TB, v bool) {
|
||||||
|
if v != true {
|
||||||
|
t.Fatal("expected false to be true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mt := mocktesting.NewT("TestMyBoolean")
|
||||||
|
mt.Run("true", func(t testing.TB) {
|
||||||
|
requireTrue(t, true)
|
||||||
|
})
|
||||||
|
fmt.Printf("Name: %s\n", mt.Name())
|
||||||
|
fmt.Printf("Failed: %+v\n", mt.Failed())
|
||||||
|
fmt.Printf("Sub1-Name: %s\n", mt.Subtests()[0].Name())
|
||||||
|
fmt.Printf("Sub1-Failed: %+v\n", mt.Subtests()[0].Failed())
|
||||||
|
fmt.Printf("Sub1-Aborted: %+v\n", mt.Subtests()[0].Aborted())
|
||||||
|
|
||||||
|
mt.Run("false", func(t testing.TB) {
|
||||||
|
requireTrue(t, false)
|
||||||
|
fmt.Println("This is never executed.")
|
||||||
|
})
|
||||||
|
fmt.Printf("Failed: %+v\n", mt.Failed())
|
||||||
|
fmt.Printf("Sub2-Name: %s\n", mt.Subtests()[1].Name())
|
||||||
|
fmt.Printf("Sub2-Failed: %+v\n", mt.Subtests()[1].Failed())
|
||||||
|
fmt.Printf("Sub2-Aborted: %+v\n", mt.Subtests()[1].Aborted())
|
||||||
|
fmt.Printf("Sub2-Output: %s\n", strings.Join(mt.Subtests()[1].Output(), ""))
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// Name: TestMyBoolean
|
||||||
|
// Failed: false
|
||||||
|
// Sub1-Name: TestMyBoolean/true
|
||||||
|
// Sub1-Failed: false
|
||||||
|
// Sub1-Aborted: false
|
||||||
|
// Failed: true
|
||||||
|
// Sub2-Name: TestMyBoolean/false
|
||||||
|
// Sub2-Failed: true
|
||||||
|
// Sub2-Aborted: true
|
||||||
|
// Sub2-Output: expected false to be true
|
||||||
|
}
|
||||||
|
|
||||||
|
func Example_subtests_in_subtests() {
|
||||||
|
assertGreaterThan := func(t testing.TB, got int, min int) {
|
||||||
|
if got <= min {
|
||||||
|
t.Errorf("expected %d to be greater than %d", got, min)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mt := mocktesting.NewT("TestMyBoolean")
|
||||||
|
mt.Run("positive", func(t testing.TB) {
|
||||||
|
subMT, _ := t.(*mocktesting.T)
|
||||||
|
|
||||||
|
subMT.Run("greater than", func(t testing.TB) {
|
||||||
|
assertGreaterThan(t, 5, 4)
|
||||||
|
})
|
||||||
|
subMT.Run("equal", func(t testing.TB) {
|
||||||
|
assertGreaterThan(t, 5, 5)
|
||||||
|
})
|
||||||
|
subMT.Run("less than", func(t testing.TB) {
|
||||||
|
assertGreaterThan(t, 4, 5)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
fmt.Printf("Name: %s\n", mt.Name())
|
||||||
|
fmt.Printf("Failed: %+v\n", mt.Failed())
|
||||||
|
fmt.Printf("Sub1-Name: %s\n", mt.Subtests()[0].Name())
|
||||||
|
fmt.Printf("Sub1-Failed: %+v\n", mt.Subtests()[0].Failed())
|
||||||
|
fmt.Printf("Sub1-Aborted: %+v\n", mt.Subtests()[0].Aborted())
|
||||||
|
fmt.Printf("Sub1-Sub1-Name: %s\n", mt.Subtests()[0].Subtests()[0].Name())
|
||||||
|
fmt.Printf(
|
||||||
|
"Sub1-Sub1-Failed: %+v\n", mt.Subtests()[0].Subtests()[0].Failed(),
|
||||||
|
)
|
||||||
|
fmt.Printf(
|
||||||
|
"Sub1-Sub1-Aborted: %+v\n", mt.Subtests()[0].Subtests()[0].Aborted(),
|
||||||
|
)
|
||||||
|
fmt.Printf("Sub1-Sub1-Name: %s\n", mt.Subtests()[0].Subtests()[1].Name())
|
||||||
|
fmt.Printf(
|
||||||
|
"Sub1-Sub2-Failed: %+v\n", mt.Subtests()[0].Subtests()[1].Failed(),
|
||||||
|
)
|
||||||
|
fmt.Printf(
|
||||||
|
"Sub1-Sub2-Aborted: %+v\n", mt.Subtests()[0].Subtests()[1].Aborted(),
|
||||||
|
)
|
||||||
|
fmt.Printf(
|
||||||
|
"Sub1-Sub3-Output: %s\n", strings.TrimSpace(
|
||||||
|
strings.Join(mt.Subtests()[0].Subtests()[1].Output(), ""),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
fmt.Printf("Sub1-Sub1-Name: %s\n", mt.Subtests()[0].Subtests()[2].Name())
|
||||||
|
fmt.Printf(
|
||||||
|
"Sub1-Sub3-Failed: %+v\n", mt.Subtests()[0].Subtests()[2].Failed(),
|
||||||
|
)
|
||||||
|
fmt.Printf(
|
||||||
|
"Sub1-Sub3-Aborted: %+v\n", mt.Subtests()[0].Subtests()[2].Aborted(),
|
||||||
|
)
|
||||||
|
fmt.Printf(
|
||||||
|
"Sub1-Sub3-Output: %s\n", strings.TrimSpace(
|
||||||
|
strings.Join(mt.Subtests()[0].Subtests()[2].Output(), ""),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// Name: TestMyBoolean
|
||||||
|
// Failed: true
|
||||||
|
// Sub1-Name: TestMyBoolean/positive
|
||||||
|
// Sub1-Failed: true
|
||||||
|
// Sub1-Aborted: false
|
||||||
|
// Sub1-Sub1-Name: TestMyBoolean/positive/greater_than
|
||||||
|
// Sub1-Sub1-Failed: false
|
||||||
|
// Sub1-Sub1-Aborted: false
|
||||||
|
// Sub1-Sub1-Name: TestMyBoolean/positive/equal
|
||||||
|
// Sub1-Sub2-Failed: true
|
||||||
|
// Sub1-Sub2-Aborted: false
|
||||||
|
// Sub1-Sub3-Output: expected 5 to be greater than 5
|
||||||
|
// Sub1-Sub1-Name: TestMyBoolean/positive/less_than
|
||||||
|
// Sub1-Sub3-Failed: true
|
||||||
|
// Sub1-Sub3-Aborted: false
|
||||||
|
// Sub1-Sub3-Output: expected 4 to be greater than 5
|
||||||
|
}
|
||||||
5
go.mod
Normal file
5
go.mod
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
module github.com/jimeh/go-mocktesting
|
||||||
|
|
||||||
|
go 1.15
|
||||||
|
|
||||||
|
require github.com/stretchr/testify v1.7.0
|
||||||
11
go.sum
Normal file
11
go.sum
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||||
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
23
mocktesting.go
Normal file
23
mocktesting.go
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// Package mocktesting provides a mock of *testing.T for the purpose of testing
|
||||||
|
// test helpers.
|
||||||
|
package mocktesting
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Go runs the provided function in a new goroutine, and blocks until the
|
||||||
|
// goroutine has exited.
|
||||||
|
//
|
||||||
|
// This is essentially a helper function to avoid aborting the current goroutine
|
||||||
|
// when a *T instance aborts the goroutine that any of FailNow(), Fatal(),
|
||||||
|
// Fatalf(), SkipNow(), Skip(), or Skipf() are called from.
|
||||||
|
func Go(f func()) {
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
f()
|
||||||
|
}()
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
30
mocktesting_test.go
Normal file
30
mocktesting_test.go
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
package mocktesting
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
func runInGoroutine(f func()) {
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
f()
|
||||||
|
}()
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func stringsUniq(strs []string) []string {
|
||||||
|
m := map[string]bool{}
|
||||||
|
|
||||||
|
for _, s := range strs {
|
||||||
|
m[s] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
r := make([]string, 0, len(m))
|
||||||
|
for s := range m {
|
||||||
|
r = append(r, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
426
t.go
Normal file
426
t.go
Normal file
@@ -0,0 +1,426 @@
|
|||||||
|
package mocktesting
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestingT is an interface covering *mocktesting.T's internal use of
|
||||||
|
// *testing.T. See WithTestingT() for more details.
|
||||||
|
type TestingT interface {
|
||||||
|
Fatal(args ...interface{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// T is a fake/mock implementation of testing.T. It records all actions
|
||||||
|
// performed via all methods on the testing.T interface, so they can be
|
||||||
|
// inspected and asserted.
|
||||||
|
//
|
||||||
|
// It is specifically intended for testing test helpers which accept a
|
||||||
|
// *testing.T or *testing.B, so you can verify that the helpers call Fatal(),
|
||||||
|
// Error(), etc, as they need.
|
||||||
|
type T struct {
|
||||||
|
name string
|
||||||
|
abort bool
|
||||||
|
baseTempdir string
|
||||||
|
testingT TestingT
|
||||||
|
deadline time.Time
|
||||||
|
timeout bool
|
||||||
|
|
||||||
|
mux sync.RWMutex
|
||||||
|
skipped bool
|
||||||
|
failed int
|
||||||
|
parallel bool
|
||||||
|
output []string
|
||||||
|
helpers []string
|
||||||
|
aborted bool
|
||||||
|
cleanups []func()
|
||||||
|
env map[string]string
|
||||||
|
subtests []*T
|
||||||
|
tempdirs []string
|
||||||
|
|
||||||
|
// subtestNames is used to ensure subtests do not have conflicting names.
|
||||||
|
subtestNames map[string]bool
|
||||||
|
|
||||||
|
// mkdirTempFunc is used by the TempDir function instead of ioutil.TempDir()
|
||||||
|
// if it is not nil. This is only used by tests for TempDir itself to ensure
|
||||||
|
// it behaves correctly if temp directory creation fails.
|
||||||
|
mkdirTempFunc func(string, string) (string, error)
|
||||||
|
|
||||||
|
// Embed *testing.T to implement the testing.TB interface, which has a
|
||||||
|
// private method to prevent it from being implemented. However that means
|
||||||
|
// it's very difficult to test testing helpers.
|
||||||
|
*testing.T
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure T struct implements testing.TB interface.
|
||||||
|
var _ testing.TB = (*T)(nil)
|
||||||
|
|
||||||
|
func NewT(name string, options ...Option) *T {
|
||||||
|
t := &T{
|
||||||
|
name: strings.ReplaceAll(name, " ", "_"),
|
||||||
|
abort: true,
|
||||||
|
baseTempdir: os.TempDir(),
|
||||||
|
deadline: time.Now().Add(10 * time.Minute),
|
||||||
|
timeout: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, opt := range options {
|
||||||
|
opt.apply(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
type Option interface {
|
||||||
|
apply(*T)
|
||||||
|
}
|
||||||
|
|
||||||
|
type optionFunc func(*T)
|
||||||
|
|
||||||
|
func (fn optionFunc) apply(g *T) {
|
||||||
|
fn(g)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithTimeout specifies a custom timeout for the mock test. It effectively
|
||||||
|
// determines the return values of Deadline().
|
||||||
|
//
|
||||||
|
// When given a zero-value time.Duration, Deadline() will act as if no timeout
|
||||||
|
// has been set.
|
||||||
|
//
|
||||||
|
// If this option is not used, the default timeout value is set to 10 minutes.
|
||||||
|
func WithTimeout(d time.Duration) Option {
|
||||||
|
return optionFunc(func(t *T) {
|
||||||
|
if d > 0 {
|
||||||
|
t.timeout = true
|
||||||
|
t.deadline = time.Now().Add(d)
|
||||||
|
} else {
|
||||||
|
t.timeout = false
|
||||||
|
t.deadline = time.Time{}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithDeadline specifies a custom timeout for the mock test, but setting the
|
||||||
|
// deadline to an exact value, rather than setting it based on the offset from
|
||||||
|
// now of a time.Duration. It effectively determines the return values of
|
||||||
|
// Deadline().
|
||||||
|
//
|
||||||
|
// When given a empty time.Time{}, Deadline() will act as if no timeout has been
|
||||||
|
// set.
|
||||||
|
//
|
||||||
|
// If this option is not used, the default timeout value is set to 10 minutes.
|
||||||
|
func WithDeadline(d time.Time) Option {
|
||||||
|
return optionFunc(func(t *T) {
|
||||||
|
if d != (time.Time{}) {
|
||||||
|
t.timeout = true
|
||||||
|
t.deadline = d
|
||||||
|
} else {
|
||||||
|
t.timeout = false
|
||||||
|
t.deadline = time.Time{}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithNoAbort disables aborting the current goroutine with runtime.Goexit()
|
||||||
|
// when SkipNow or FailNow is called. This should be used with care, as it
|
||||||
|
// causes behavior to diverge from normal *tesing.T, as code after calling
|
||||||
|
// t.Fatal() will be executed.
|
||||||
|
func WithNoAbort() Option {
|
||||||
|
return optionFunc(func(t *T) {
|
||||||
|
t.abort = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithBaseTempdir sets the base directory that TempDir() creates temporary
|
||||||
|
// directories within.
|
||||||
|
//
|
||||||
|
// If this option is not used, the default base directory used is os.TempDir().
|
||||||
|
func WithBaseTempdir(dir string) Option {
|
||||||
|
return optionFunc(func(t *T) {
|
||||||
|
if dir != "" {
|
||||||
|
t.baseTempdir = dir
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithTestingT accepts a *testing.T instance which is used to report internal
|
||||||
|
// errors within *mocktesting.T itself. For example if the TempDir() function
|
||||||
|
// fails to create a temporary directory on disk, it will call Fatal() on the
|
||||||
|
// *testing.T instance provided here.
|
||||||
|
//
|
||||||
|
// If this option is not used, internal errors will instead cause a panic.
|
||||||
|
func WithTestingT(testingT TestingT) Option {
|
||||||
|
return optionFunc(func(t *T) {
|
||||||
|
t.testingT = testingT
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *T) goexit() {
|
||||||
|
t.aborted = true
|
||||||
|
if t.abort {
|
||||||
|
runtime.Goexit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *T) internalError(err error) {
|
||||||
|
err = fmt.Errorf("mocktesting: %w", err)
|
||||||
|
|
||||||
|
if t.testingT != nil {
|
||||||
|
t.testingT.Fatal(err)
|
||||||
|
} else {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *T) Name() string {
|
||||||
|
return t.name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *T) Deadline() (time.Time, bool) {
|
||||||
|
return t.deadline, t.timeout
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *T) Error(args ...interface{}) {
|
||||||
|
t.Log(args...)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *T) Errorf(format string, args ...interface{}) {
|
||||||
|
t.Logf(format, args...)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *T) Fail() {
|
||||||
|
t.failed++
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *T) FailNow() {
|
||||||
|
t.Fail()
|
||||||
|
t.goexit()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *T) Failed() bool {
|
||||||
|
return t.failed > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *T) Fatal(args ...interface{}) {
|
||||||
|
t.Log(args...)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *T) Fatalf(format string, args ...interface{}) {
|
||||||
|
t.Logf(format, args...)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *T) Log(args ...interface{}) {
|
||||||
|
t.mux.Lock()
|
||||||
|
defer t.mux.Unlock()
|
||||||
|
|
||||||
|
t.output = append(t.output, fmt.Sprintln(args...))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *T) Logf(format string, args ...interface{}) {
|
||||||
|
t.mux.Lock()
|
||||||
|
defer t.mux.Unlock()
|
||||||
|
|
||||||
|
if len(format) == 0 || format[len(format)-1] != '\n' {
|
||||||
|
format += "\n"
|
||||||
|
}
|
||||||
|
t.output = append(t.output, fmt.Sprintf(format, args...))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *T) Parallel() {
|
||||||
|
t.parallel = true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *T) Skip(args ...interface{}) {
|
||||||
|
t.Log(args...)
|
||||||
|
t.SkipNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *T) Skipf(format string, args ...interface{}) {
|
||||||
|
t.Logf(format, args...)
|
||||||
|
t.SkipNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *T) SkipNow() {
|
||||||
|
t.skipped = true
|
||||||
|
t.goexit()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *T) Skipped() bool {
|
||||||
|
return t.skipped
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *T) Helper() {
|
||||||
|
pc, _, _, ok := runtime.Caller(1)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fnName := runtime.FuncForPC(pc).Name()
|
||||||
|
|
||||||
|
t.mux.Lock()
|
||||||
|
defer t.mux.Unlock()
|
||||||
|
|
||||||
|
t.helpers = append(t.helpers, fnName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *T) Cleanup(f func()) {
|
||||||
|
t.mux.Lock()
|
||||||
|
defer t.mux.Unlock()
|
||||||
|
|
||||||
|
t.cleanups = append(t.cleanups, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *T) TempDir() string {
|
||||||
|
// Allow setting MkdirTemp function for testing purposes.
|
||||||
|
f := t.mkdirTempFunc
|
||||||
|
if f == nil {
|
||||||
|
f = ioutil.TempDir
|
||||||
|
}
|
||||||
|
|
||||||
|
dir, err := f(t.baseTempdir, "go-mocktesting*")
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("TempDir() failed to create directory: %w", err)
|
||||||
|
t.internalError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.mux.Lock()
|
||||||
|
defer t.mux.Unlock()
|
||||||
|
t.tempdirs = append(t.tempdirs, dir)
|
||||||
|
|
||||||
|
return dir
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *T) Run(name string, f func(testing.TB)) bool {
|
||||||
|
name = t.newSubTestName(name)
|
||||||
|
fullname := name
|
||||||
|
if t.name != "" {
|
||||||
|
fullname = t.name + "/" + name
|
||||||
|
}
|
||||||
|
|
||||||
|
subtest := NewT(fullname)
|
||||||
|
subtest.abort = t.abort
|
||||||
|
subtest.baseTempdir = t.baseTempdir
|
||||||
|
subtest.testingT = t.testingT
|
||||||
|
subtest.deadline = t.deadline
|
||||||
|
subtest.timeout = t.timeout
|
||||||
|
|
||||||
|
if t.subtestNames == nil {
|
||||||
|
t.subtestNames = map[string]bool{}
|
||||||
|
}
|
||||||
|
|
||||||
|
t.mux.Lock()
|
||||||
|
t.subtests = append(t.subtests, subtest)
|
||||||
|
t.subtestNames[name] = true
|
||||||
|
t.mux.Unlock()
|
||||||
|
|
||||||
|
Go(func() {
|
||||||
|
f(subtest)
|
||||||
|
})
|
||||||
|
|
||||||
|
if subtest.Failed() {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
return !subtest.Failed()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *T) newSubTestName(name string) string {
|
||||||
|
name = strings.ReplaceAll(name, " ", "_")
|
||||||
|
|
||||||
|
if !t.subtestNames[name] {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
|
i := 1
|
||||||
|
for {
|
||||||
|
n := name + "#" + fmt.Sprintf("%02d", i)
|
||||||
|
if !t.subtestNames[n] {
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Inspection Methods which are not part of the testing.TB interface.
|
||||||
|
//
|
||||||
|
|
||||||
|
// Output returns a string slice of all output produced by calls to Log(),
|
||||||
|
// Logf(), Error(), Errorf(), Fatal(), Fatalf(), Skip(), and Skipf().
|
||||||
|
func (t *T) Output() []string {
|
||||||
|
t.mux.RLock()
|
||||||
|
defer t.mux.RUnlock()
|
||||||
|
|
||||||
|
return t.output
|
||||||
|
}
|
||||||
|
|
||||||
|
// CleanupFuncs returns a slice of functions given to Cleanup().
|
||||||
|
func (t *T) CleanupFuncs() []func() {
|
||||||
|
t.mux.RLock()
|
||||||
|
defer t.mux.RUnlock()
|
||||||
|
|
||||||
|
return t.cleanups
|
||||||
|
}
|
||||||
|
|
||||||
|
// CleanupNames returns a string slice of function names given to Cleanup().
|
||||||
|
func (t *T) CleanupNames() []string {
|
||||||
|
r := make([]string, 0, len(t.cleanups))
|
||||||
|
for _, f := range t.cleanups {
|
||||||
|
p := reflect.ValueOf(f).Pointer()
|
||||||
|
r = append(r, runtime.FuncForPC(p).Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// FailedCount returns the number of times Error(), Errorf(), Fail(), Failf(),
|
||||||
|
// FailNow(), Fatal(), and Fatalf() were called.
|
||||||
|
func (t *T) FailedCount() int {
|
||||||
|
return t.failed
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aborted returns true if the TB instance aborted the current goroutine via
|
||||||
|
// runtime.Goexit(), which is called by FailNow() and SkipNow().
|
||||||
|
func (t *T) Aborted() bool {
|
||||||
|
return t.aborted
|
||||||
|
}
|
||||||
|
|
||||||
|
// HelperNames returns a list of function names which called Helper().
|
||||||
|
func (t *T) HelperNames() []string {
|
||||||
|
t.mux.RLock()
|
||||||
|
defer t.mux.RUnlock()
|
||||||
|
|
||||||
|
return t.helpers
|
||||||
|
}
|
||||||
|
|
||||||
|
// Paralleled returns true if Parallel() has been called.
|
||||||
|
func (t *T) Paralleled() bool {
|
||||||
|
return t.parallel
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subtests returns a list map of *TB instances for any subtests executed via
|
||||||
|
// Run().
|
||||||
|
func (t *T) Subtests() []*T {
|
||||||
|
if t.subtests == nil {
|
||||||
|
t.mux.Lock()
|
||||||
|
t.subtests = []*T{}
|
||||||
|
t.mux.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
t.mux.RLock()
|
||||||
|
defer t.mux.RUnlock()
|
||||||
|
|
||||||
|
return t.subtests
|
||||||
|
}
|
||||||
31
t_go116.go
Normal file
31
t_go116.go
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
//go:build go1.16
|
||||||
|
// +build go1.16
|
||||||
|
|
||||||
|
package mocktesting
|
||||||
|
|
||||||
|
func (t *T) Setenv(key string, value string) {
|
||||||
|
t.mux.Lock()
|
||||||
|
defer t.mux.Unlock()
|
||||||
|
|
||||||
|
if t.env == nil {
|
||||||
|
t.env = map[string]string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
if key != "" {
|
||||||
|
t.env[key] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getenv returns a map[string]string of keys/values given to Setenv().
|
||||||
|
func (t *T) Getenv() map[string]string {
|
||||||
|
if t.env == nil {
|
||||||
|
t.mux.Lock()
|
||||||
|
t.env = map[string]string{}
|
||||||
|
t.mux.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
t.mux.RLock()
|
||||||
|
defer t.mux.RUnlock()
|
||||||
|
|
||||||
|
return t.env
|
||||||
|
}
|
||||||
182
t_go116_test.go
Normal file
182
t_go116_test.go
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
//go:build go1.16
|
||||||
|
// +build go1.16
|
||||||
|
|
||||||
|
package mocktesting
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestT_Setenv(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
env map[string]string
|
||||||
|
}
|
||||||
|
type args struct {
|
||||||
|
key string
|
||||||
|
value string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
args args
|
||||||
|
want map[string]string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "empty key and value",
|
||||||
|
args: args{},
|
||||||
|
want: map[string]string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "empty key",
|
||||||
|
args: args{value: "bar"},
|
||||||
|
want: map[string]string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "empty value",
|
||||||
|
args: args{key: "foo"},
|
||||||
|
want: map[string]string{"foo": ""},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "key and value",
|
||||||
|
args: args{key: "foo", value: "bar"},
|
||||||
|
want: map[string]string{"foo": "bar"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "add to existing",
|
||||||
|
fields: fields{env: map[string]string{"hello": "world"}},
|
||||||
|
args: args{key: "foo", value: "bar"},
|
||||||
|
want: map[string]string{"hello": "world", "foo": "bar"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "overwrite existing",
|
||||||
|
fields: fields{env: map[string]string{"foo": "world"}},
|
||||||
|
args: args{key: "foo", value: "bar"},
|
||||||
|
want: map[string]string{"foo": "bar"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
mt := &T{env: tt.fields.env}
|
||||||
|
|
||||||
|
mt.Setenv(tt.args.key, tt.args.value)
|
||||||
|
|
||||||
|
assert.Equal(t, tt.want, mt.env)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestT_Getenv(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
env map[string]string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
want map[string]string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "nil env",
|
||||||
|
want: map[string]string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "empty env",
|
||||||
|
fields: fields{env: map[string]string{}},
|
||||||
|
want: map[string]string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "env",
|
||||||
|
fields: fields{
|
||||||
|
env: map[string]string{
|
||||||
|
"hello": "world",
|
||||||
|
"foo": "bar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: map[string]string{
|
||||||
|
"hello": "world",
|
||||||
|
"foo": "bar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
mt := &T{env: tt.fields.env}
|
||||||
|
|
||||||
|
got := mt.Getenv()
|
||||||
|
|
||||||
|
assert.Equal(t, tt.want, got)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestT_Run_Go116(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
name string
|
||||||
|
abort bool
|
||||||
|
baseTempdir string
|
||||||
|
testingT testing.TB
|
||||||
|
deadline time.Time
|
||||||
|
timeout bool
|
||||||
|
}
|
||||||
|
type args struct {
|
||||||
|
f func(testing.TB)
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
args args
|
||||||
|
want *T
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "set environment variables",
|
||||||
|
fields: fields{
|
||||||
|
name: "set_environment_variables",
|
||||||
|
abort: true,
|
||||||
|
baseTempdir: os.TempDir(),
|
||||||
|
deadline: time.Now().Add(10 * time.Minute),
|
||||||
|
timeout: true,
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
f: func(t testing.TB) {
|
||||||
|
// Type assert to *TB for compatibility with Go 1.16 and
|
||||||
|
// earlier.
|
||||||
|
mt := t.(*T)
|
||||||
|
mt.Setenv("GO_ENV", "test")
|
||||||
|
mt.Setenv("FOO", "bar")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: &T{
|
||||||
|
name: "set_environment_variables",
|
||||||
|
abort: true,
|
||||||
|
baseTempdir: os.TempDir(),
|
||||||
|
deadline: time.Now().Add(10 * time.Minute),
|
||||||
|
timeout: true,
|
||||||
|
env: map[string]string{
|
||||||
|
"GO_ENV": "test",
|
||||||
|
"FOO": "bar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
mt := &T{
|
||||||
|
name: tt.fields.name,
|
||||||
|
abort: tt.fields.abort,
|
||||||
|
baseTempdir: tt.fields.baseTempdir,
|
||||||
|
testingT: tt.fields.testingT,
|
||||||
|
deadline: tt.fields.deadline,
|
||||||
|
timeout: tt.fields.timeout,
|
||||||
|
}
|
||||||
|
|
||||||
|
runInGoroutine(func() {
|
||||||
|
tt.args.f(mt)
|
||||||
|
})
|
||||||
|
|
||||||
|
assertEqualMocktestingT(t, tt.want, mt)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user