-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #70 from JosiahWitt/rename-ensurepkg
Rename `ensurepkg` to `ensurer` and `ensurepkg.Ensure` to `ensurer.E`
- Loading branch information
Showing
26 changed files
with
265 additions
and
235 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,17 @@ | ||
generate-mocks: | ||
(cd cmd/ensure; go build -o ../../tmp/ensure) && ./tmp/ensure mocks generate | ||
(cd cmd/ensure; make generate-mocks) | ||
|
||
test: | ||
go test ./... | ||
(cd cmd/ensure; make test) | ||
|
||
test-coverage: | ||
mkdir -p tmp | ||
go test ./... -coverprofile=tmp/ensure-pkg.coverage && go tool cover -html=tmp/ensure-pkg.coverage -o=tmp/coverage.html | ||
go test ./... -coverprofile=tmp/ensure.coverage && go tool cover -html=tmp/ensure.coverage -o=tmp/coverage.html | ||
(cd cmd/ensure; make test-coverage) | ||
|
||
lint: | ||
staticcheck ./... | ||
(cd cmd/ensure; staticcheck ./...) | ||
golangci-lint run | ||
(cd cmd/ensure; golangci-lint run) | ||
(cd cmd/ensure; make lint) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,5 +18,6 @@ flags: | |
package: | ||
paths: | ||
- "*.go" | ||
- "ensurer/**" | ||
- "ensurepkg/**" | ||
- "internal/**" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,118 +1,24 @@ | ||
// Package ensurepkg contains the implementation for the ensure test framework. | ||
// Use ensure.New to create a new instance of Ensure. | ||
// | ||
// Deprecated: Use the ensurer package instead. | ||
package ensurepkg | ||
|
||
import ( | ||
"runtime" | ||
"strings" | ||
"testing" | ||
|
||
"github.com/JosiahWitt/ensure/internal/testctx" | ||
"github.com/golang/mock/gomock" | ||
) | ||
|
||
//nolint:gochecknoglobals // This is stored as a variable so we can override it for tests in init_test.go. | ||
var newTestContext = testctx.New | ||
import "github.com/JosiahWitt/ensure/ensurer" | ||
|
||
// T implements a subset of methods on testing.T. | ||
// T implements a subset of methods on [testing.T]. | ||
// More methods may be added to T with a minor ensure release. | ||
type T = testctx.T | ||
// | ||
// Deprecated: Use [ensurer.T] instead. | ||
type T = ensurer.T | ||
|
||
// Ensure the actual value is correct using Chain. | ||
// Ensure ensures the actual value is correct using [Chain]. | ||
// Ensure also has methods that can be called directly. | ||
type Ensure func(actual interface{}) *Chain | ||
|
||
// Chain assertions to the ensure function call. | ||
type Chain struct { | ||
t testctx.T | ||
ctx testctx.Context | ||
actual interface{} | ||
wasRun bool | ||
} | ||
|
||
// InternalCreateDoNotCallDirectly should NOT be called directly. | ||
// Instead use `ensure := ensure.New(t)` to allow for easy test refactoring. | ||
func InternalCreateDoNotCallDirectly(t T) Ensure { | ||
const validWrapperFilePathSuffix = "/ensure.go" | ||
|
||
_, callerFilePath, _, ok := runtime.Caller(1) | ||
if !ok { | ||
t.Helper() | ||
t.Fatalf("Can't get caller from runtime") | ||
} | ||
|
||
if !strings.HasSuffix(callerFilePath, validWrapperFilePathSuffix) { | ||
t.Helper() | ||
t.Fatalf("Do not call `ensurepkg.InternalCreateDoNotCallDirectly(t)` directly. Instead use `ensure.New(t)`.") | ||
} | ||
|
||
return wrap(t) | ||
} | ||
|
||
// New creates an instance of ensure with the provided testing context. | ||
// | ||
// This allows the `ensure` package to be shadowed by the `ensure` variable, | ||
// while still allowing new instances of ensure to be created. | ||
func (e Ensure) New(t T) Ensure { | ||
return wrap(t) | ||
} | ||
|
||
// Failf fails the test immediately with a formatted message. | ||
// The formatted message follows the same format as the fmt package. | ||
func (e Ensure) Failf(format string, args ...interface{}) { | ||
c := e(nil) | ||
c.t.Helper() | ||
c.markRun() | ||
c.t.Fatalf(format, args...) | ||
} | ||
// Deprecated: Use [ensurer.E] instead. | ||
type Ensure = ensurer.E | ||
|
||
// T exposes the test context provided to ensure.New(t). | ||
// Chain chains assertions to the ensure function call. | ||
// | ||
// If an instance of *testing.T was not provided to ensure.New(t), this method cannot be used. | ||
// The test will fail immediately. | ||
func (e Ensure) T() *testing.T { | ||
c := e(nil) | ||
c.markRun() | ||
|
||
t, ok := c.t.(*testing.T) | ||
if !ok { | ||
c.t.Helper() | ||
c.t.Fatalf("An instance of *testing.T was not provided to ensure.New(t), thus T() cannot be used.") | ||
} | ||
|
||
return t | ||
} | ||
|
||
// GoMockController exposes a GoMock Controller scoped to the current test context. | ||
// Learn more about GoMock here: https://github.com/golang/mock | ||
func (e Ensure) GoMockController() *gomock.Controller { | ||
c := e(nil) | ||
c.markRun() | ||
return c.ctx.GoMockController() | ||
} | ||
|
||
func wrap(t T) Ensure { | ||
// Created outside the callback, so the same context is used across ensure calls | ||
ctx := newTestContext(t) | ||
|
||
return func(actual interface{}) *Chain { | ||
c := &Chain{ | ||
t: t, | ||
ctx: ctx, | ||
actual: actual, | ||
wasRun: false, | ||
} | ||
|
||
// Cleanup should never call Fatalf, otherwise panics are hidden, and | ||
// the Fatal message is displayed instead, which is really tricky for debugging. | ||
t.Helper() | ||
t.Cleanup(func() { | ||
if !c.wasRun { | ||
t.Helper() | ||
t.Errorf("Found ensure(<actual>) without chained assertion.") | ||
} | ||
}) | ||
|
||
return c | ||
} | ||
} | ||
// Deprecated: Use [ensurer.Chain] instead. | ||
type Chain = ensurer.Chain |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package ensurepkg | ||
package ensurer | ||
|
||
import ( | ||
"fmt" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package ensurepkg | ||
package ensurer | ||
|
||
import ( | ||
"errors" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package ensurepkg_test | ||
package ensurer_test | ||
|
||
import ( | ||
"sync" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
// Package ensurer contains the implementation for the ensure test framework. | ||
// | ||
// It is in a separate package from ensure to allow shadowing the ensure package | ||
// without losing access to the types. Use [ensure.New] to create a new instance of Ensure. | ||
package ensurer | ||
|
||
import ( | ||
"runtime" | ||
"strings" | ||
"testing" | ||
|
||
"github.com/JosiahWitt/ensure/internal/testctx" | ||
"github.com/golang/mock/gomock" | ||
) | ||
|
||
//nolint:gochecknoglobals // This is stored as a variable so we can override it for tests in init_test.go. | ||
var newTestContext = testctx.New | ||
|
||
// T implements a subset of methods on [testing.T]. | ||
// More methods may be added to T with a minor ensure release. | ||
type T = testctx.T | ||
|
||
// E ensures the actual value is correct using [Chain]. | ||
// E also has methods that can be called directly. | ||
type E func(actual interface{}) *Chain | ||
|
||
// Chain chains assertions to the ensure function call. | ||
type Chain struct { | ||
t testctx.T | ||
ctx testctx.Context | ||
actual interface{} | ||
wasRun bool | ||
} | ||
|
||
// InternalCreateDoNotCallDirectly should NOT be called directly. | ||
// Instead use [ensure.New] (`ensure := ensure.New(t)`) to allow for easy test refactoring. | ||
func InternalCreateDoNotCallDirectly(t T) E { | ||
const validWrapperFilePathSuffix = "/ensure.go" | ||
|
||
_, callerFilePath, _, ok := runtime.Caller(1) | ||
if !ok { | ||
t.Helper() | ||
t.Fatalf("Can't get caller from runtime") | ||
} | ||
|
||
if !strings.HasSuffix(callerFilePath, validWrapperFilePathSuffix) { | ||
t.Helper() | ||
t.Fatalf("Do not call `ensurer.InternalCreateDoNotCallDirectly(t)` directly. Instead use `ensure := ensure.New(t)`.") | ||
} | ||
|
||
return wrap(t) | ||
} | ||
|
||
// New creates an instance of ensure with the provided testing context. | ||
// | ||
// This allows the `ensure` package to be shadowed by the `ensure` variable, | ||
// while still allowing new instances of ensure to be created. | ||
func (e E) New(t T) E { | ||
return wrap(t) | ||
} | ||
|
||
// Failf fails the test immediately with a formatted message. | ||
// The formatted message follows the same format as the fmt package. | ||
func (e E) Failf(format string, args ...interface{}) { | ||
c := e(nil) | ||
c.t.Helper() | ||
c.markRun() | ||
c.t.Fatalf(format, args...) | ||
} | ||
|
||
// T exposes the scoped [testing.T]. | ||
// | ||
// If an instance of *testing.T was not provided to ensure.New(t), this method cannot be used. | ||
// The test will fail immediately. | ||
func (e E) T() *testing.T { | ||
c := e(nil) | ||
c.markRun() | ||
|
||
t, ok := c.t.(*testing.T) | ||
if !ok { | ||
c.t.Helper() | ||
c.t.Fatalf("An instance of *testing.T was not provided to ensure.New(t), thus T() cannot be used.") | ||
} | ||
|
||
return t | ||
} | ||
|
||
// GoMockController exposes a GoMock Controller scoped to the current test context. | ||
// Learn more about GoMock here: https://github.com/golang/mock | ||
func (e E) GoMockController() *gomock.Controller { | ||
c := e(nil) | ||
c.markRun() | ||
return c.ctx.GoMockController() | ||
} | ||
|
||
func wrap(t T) E { | ||
// Created outside the callback, so the same context is used across ensure calls | ||
ctx := newTestContext(t) | ||
|
||
return func(actual interface{}) *Chain { | ||
c := &Chain{ | ||
t: t, | ||
ctx: ctx, | ||
actual: actual, | ||
wasRun: false, | ||
} | ||
|
||
// Cleanup should never call Fatalf, otherwise panics are hidden, and | ||
// the Fatal message is displayed instead, which is really tricky for debugging. | ||
t.Helper() | ||
t.Cleanup(func() { | ||
if !c.wasRun { | ||
t.Helper() | ||
t.Errorf("Found ensure(<actual>) without chained assertion.") | ||
} | ||
}) | ||
|
||
return c | ||
} | ||
} |
Oops, something went wrong.