checkers

package
v1.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 3, 2024 License: MIT Imports: 13 Imported by: 0

Documentation

Index

Constants

View Source
const DefaultSuiteExtraAssertCallMode = SuiteExtraAssertCallModeRemove

Variables

View Source
var DefaultExpectedVarPattern = regexp.MustCompile(
	`(^(exp(ected)?|want(ed)?)([A-Z]\w*)?$)|(^(\w*[a-z])?(Exp(ected)?|Want(ed)?)$)`)

DefaultExpectedVarPattern matches variables with "expected" or "wanted" prefix or suffix in the name.

Functions

func All

func All() []string

All returns all checkers names sorted by checker's priority.

func EnabledByDefault

func EnabledByDefault() []string

EnabledByDefault returns checkers enabled by default sorted by checker's priority.

func IsEnabledByDefault

func IsEnabledByDefault(name string) bool

IsEnabledByDefault returns true if a checker is enabled by default. Returns false if there is no such checker in the registry. For pre-validation use Get or IsKnown.

func IsKnown

func IsKnown(name string) bool

IsKnown checks if there is a checker with that name.

func SortByPriority

func SortByPriority(checkers []string)

SortByPriority mutates the input checkers names by sorting them in checker priority order. Ignores unknown checkers. For pre-validation use Get or IsKnown.

Types

type AdvancedChecker

type AdvancedChecker interface {
	Checker
	Check(pass *analysis.Pass, inspector *inspector.Inspector) []analysis.Diagnostic
}

AdvancedChecker implements complex Check logic different from trivial CallMeta check.

type BlankImport added in v1.1.0

type BlankImport struct{}

BlankImport detects useless blank imports of testify's packages. These imports are useless since testify doesn't do any magic with init() function.

The checker detects situations like

import (
	"testing"

	_ "github.com/stretchr/testify"
	_ "github.com/stretchr/testify/assert"
	_ "github.com/stretchr/testify/http"
	_ "github.com/stretchr/testify/mock"
	_ "github.com/stretchr/testify/require"
	_ "github.com/stretchr/testify/suite"
)

and requires

import (
	"testing"
)

func NewBlankImport added in v1.1.0

func NewBlankImport() BlankImport

NewBlankImport constructs BlankImport checker.

func (BlankImport) Check added in v1.1.0

func (checker BlankImport) Check(pass *analysis.Pass, _ *inspector.Inspector) (diagnostics []analysis.Diagnostic)

func (BlankImport) Name added in v1.1.0

func (BlankImport) Name() string

type BoolCompare

type BoolCompare struct {
	// contains filtered or unexported fields
}

BoolCompare detects situations like

assert.Equal(t, false, result)
assert.EqualValues(t, false, result)
assert.Exactly(t, false, result)
assert.NotEqual(t, true, result)
assert.NotEqualValues(t, true, result)
assert.False(t, !result)
assert.True(t, result == true)
...

and requires

assert.False(t, result)
assert.True(t, result)

func NewBoolCompare

func NewBoolCompare() *BoolCompare

NewBoolCompare constructs BoolCompare checker.

func (BoolCompare) Check

func (checker BoolCompare) Check(pass *analysis.Pass, call *CallMeta) *analysis.Diagnostic

func (BoolCompare) Name

func (BoolCompare) Name() string

func (*BoolCompare) SetIgnoreCustomTypes added in v1.2.0

func (checker *BoolCompare) SetIgnoreCustomTypes(v bool) *BoolCompare

type CallMeta

type CallMeta struct {
	// Range contains start and end position of assertion call.
	analysis.Range
	// IsPkg true if this is package (not object) call.
	IsPkg bool
	// IsAssert true if this is "testify/assert" package (or object) call.
	IsAssert bool
	// Selector is the AST expression of "assert.Equal".
	Selector *ast.SelectorExpr
	// SelectorXStr is a string representation of Selector's left part – value before point, e.g. "assert".
	SelectorXStr string
	// Fn stores meta info about assertion function itself.
	Fn FnMeta
	// Args stores assertion call arguments but without `t *testing.T` argument.
	// E.g [42, result, "helpful comment"].
	Args []ast.Expr
	// ArgsRaw stores assertion call initial arguments.
	// E.g [t, 42, result, "helpful comment"].
	ArgsRaw []ast.Expr
}

CallMeta stores meta info about assertion function/method call, for example

assert.Equal(t, 42, result, "helpful comment")

func NewCallMeta added in v1.0.0

func NewCallMeta(pass *analysis.Pass, ce *ast.CallExpr) *CallMeta

NewCallMeta returns meta information about testify assertion call. Returns nil if ast.CallExpr is not testify call.

func (CallMeta) String added in v1.0.0

func (c CallMeta) String() string

type Checker

type Checker interface {
	Name() string
}

Checker describes named checker.

func Get

func Get(name string) (Checker, bool)

Get returns new checker instance by checker's name.

type Compares

type Compares struct{}

Compares detects situations like

assert.True(t, a == b)
assert.True(t, a != b)
assert.True(t, a > b)
assert.True(t, a >= b)
assert.True(t, a < b)
assert.True(t, a <= b)
assert.False(t, a == b)
...

and requires

assert.Equal(t, a, b)
assert.NotEqual(t, a, b)
assert.Greater(t, a, b)
assert.GreaterOrEqual(t, a, b)
assert.Less(t, a, b)
assert.LessOrEqual(t, a, b)

func NewCompares

func NewCompares() Compares

NewCompares constructs Compares checker.

func (Compares) Check

func (checker Compares) Check(pass *analysis.Pass, call *CallMeta) *analysis.Diagnostic

func (Compares) Name

func (Compares) Name() string

type Empty

type Empty struct{}

Empty detects situations like

assert.Len(t, arr, 0)
assert.Equal(t, 0, len(arr))
assert.EqualValues(t, 0, len(arr))
assert.Exactly(t, 0, len(arr))
assert.LessOrEqual(t, len(arr), 0)
assert.GreaterOrEqual(t, 0, len(arr))
assert.Less(t, len(arr), 0)
assert.Greater(t, 0, len(arr))
assert.Less(t, len(arr), 1)
assert.Greater(t, 1, len(arr))

assert.NotEqual(t, 0, len(arr))
assert.NotEqualValues(t, 0, len(arr))
assert.Less(t, 0, len(arr))
assert.Greater(t, len(arr), 0)

and requires

assert.Empty(t, arr)
assert.NotEmpty(t, arr)

func NewEmpty

func NewEmpty() Empty

NewEmpty constructs Empty checker.

func (Empty) Check

func (checker Empty) Check(pass *analysis.Pass, call *CallMeta) *analysis.Diagnostic

func (Empty) Name

func (Empty) Name() string

type ErrorIsAs

type ErrorIsAs struct{}

ErrorIsAs detects situations like

assert.Error(t, err, errSentinel)
assert.NoError(t, err, errSentinel)
assert.True(t, errors.Is(err, errSentinel))
assert.False(t, errors.Is(err, errSentinel))
assert.True(t, errors.As(err, &target))

and requires

assert.ErrorIs(t, err, errSentinel)
assert.NotErrorIs(t, err, errSentinel)
assert.ErrorAs(t, err, &target)

Also ErrorIsAs repeats go vet's "errorsas" check logic.

func NewErrorIsAs

func NewErrorIsAs() ErrorIsAs

NewErrorIsAs constructs ErrorIsAs checker.

func (ErrorIsAs) Check

func (checker ErrorIsAs) Check(pass *analysis.Pass, call *CallMeta) *analysis.Diagnostic

func (ErrorIsAs) Name

func (ErrorIsAs) Name() string

type ErrorNil

type ErrorNil struct{}

ErrorNil detects situations like

assert.Nil(t, err)
assert.NotNil(t, err)
assert.Equal(t, nil, err)
assert.EqualValues(t, nil, err)
assert.Exactly(t, nil, err)
assert.ErrorIs(t, err, nil)

assert.NotEqual(t, nil, err)
assert.NotEqualValues(t, nil, err)
assert.NotErrorIs(t, err, nil)

and requires

assert.NoError(t, err)
assert.Error(t, err)

func NewErrorNil

func NewErrorNil() ErrorNil

NewErrorNil constructs ErrorNil checker.

func (ErrorNil) Check

func (checker ErrorNil) Check(pass *analysis.Pass, call *CallMeta) *analysis.Diagnostic

func (ErrorNil) Name

func (ErrorNil) Name() string

type ExpectedActual

type ExpectedActual struct {
	// contains filtered or unexported fields
}

ExpectedActual detects situation like

assert.Equal(t, result, expected)
assert.EqualExportedValues(t, resultObj, User{Name: "Anton"})
assert.EqualValues(t, result, 42)
assert.Exactly(t, result, int64(42))
assert.JSONEq(t, result, `{"version": 3}`)
assert.InDelta(t, result, 42.42, 1.0)
assert.InDeltaMapValues(t, result, map[string]float64{"score": 0.99}, 1.0)
assert.InDeltaSlice(t, result, []float64{0.98, 0.99}, 1.0)
assert.InEpsilon(t, result, 42.42, 0.0001)
assert.InEpsilonSlice(t, result, []float64{0.9801, 0.9902}, 0.0001)
assert.IsType(t, result, (*User)(nil))
assert.NotEqual(t, result, "expected")
assert.NotEqualValues(t, result, "expected")
assert.NotSame(t, resultPtr, &value)
assert.Same(t, resultPtr, &value)
assert.WithinDuration(t, resultTime, time.Date(2023, 01, 12, 11, 46, 33, 0, nil), time.Second)
assert.YAMLEq(t, result, "version: '3'")

and requires

assert.Equal(t, expected, result)
assert.EqualExportedValues(t, User{Name: "Anton"}, resultObj)
assert.EqualValues(t, 42, result)
...

func NewExpectedActual

func NewExpectedActual() *ExpectedActual

NewExpectedActual constructs ExpectedActual checker using DefaultExpectedVarPattern.

func (ExpectedActual) Check

func (checker ExpectedActual) Check(pass *analysis.Pass, call *CallMeta) *analysis.Diagnostic

func (ExpectedActual) Name

func (ExpectedActual) Name() string

func (*ExpectedActual) SetExpVarPattern

func (checker *ExpectedActual) SetExpVarPattern(p *regexp.Regexp) *ExpectedActual

type FloatCompare

type FloatCompare struct{}

FloatCompare detects situation like

assert.Equal(t, 42.42, result)
assert.EqualValues(t, 42.42, result)
assert.Exactly(t, 42.42, result)
assert.True(t, result == 42.42)
assert.False(t, result != 42.42)

and requires

assert.InEpsilon(t, 42.42, result, 0.0001) // Or assert.InDelta

func NewFloatCompare

func NewFloatCompare() FloatCompare

NewFloatCompare constructs FloatCompare checker.

func (FloatCompare) Check

func (checker FloatCompare) Check(pass *analysis.Pass, call *CallMeta) *analysis.Diagnostic

func (FloatCompare) Name

func (FloatCompare) Name() string

type FnMeta

type FnMeta struct {
	// Range contains start and end position of function Name.
	analysis.Range
	// Name is a function name.
	Name string
	// NameFTrimmed is a function name without "f" suffix.
	NameFTrimmed string
	// IsFmt is true if function is formatted, e.g. "Equalf".
	IsFmt bool
}

FnMeta stores meta info about assertion function itself, for example "Equal".

type GoRequire added in v1.0.0

type GoRequire struct{}

GoRequire takes idea from go vet's "testinggoroutine" check and detects usage of require package's functions or assert.FailNow in the non-test goroutines

go func() {
	conn, err = lis.Accept()
	require.NoError(t, err)

	if assert.Error(err) {
		assert.FailNow(t, msg)
	}
}()

func NewGoRequire added in v1.0.0

func NewGoRequire() GoRequire

NewGoRequire constructs GoRequire checker.

func (GoRequire) Check added in v1.0.0

func (checker GoRequire) Check(pass *analysis.Pass, inspector *inspector.Inspector) (diagnostics []analysis.Diagnostic)

Check should be consistent with https://cs.opensource.google/go/x/tools/+/master:go/analysis/passes/testinggoroutine/testinggoroutine.go

But due to the fact that the Check covers cases missed by go vet, the implementation turned out to be terribly complicated.

In simple words, the algorithm is as follows:

  • we walk along the call tree and store the status, whether we are in the test goroutine or not;
  • if we are in a test goroutine, then require is allowed, otherwise not;
  • when we encounter the launch of a subtest or `go` statement, the status changes;
  • in order to correctly handle the return to the correct status when exiting the current function, we have to store a stack of statuses (inGoroutineRunningTestFunc).

Other test functions called in the test function are also analyzed to make a verdict about the current function. This leads to recursion, which the cache of processed functions (processedFuncs) helps reduce the impact of. Also, because of this, we have to pre-collect a list of test function declarations (testsDecls).

func (GoRequire) Name added in v1.0.0

func (GoRequire) Name() string

type Len

type Len struct{}

Len detects situations like

assert.Equal(t, 3, len(arr))
assert.EqualValues(t, 3, len(arr))
assert.Exactly(t, 3, len(arr))
assert.True(t, len(arr) == 3)

and requires

assert.Len(t, arr, 3)

func NewLen

func NewLen() Len

NewLen constructs Len checker.

func (Len) Check

func (checker Len) Check(pass *analysis.Pass, call *CallMeta) *analysis.Diagnostic

func (Len) Name

func (Len) Name() string

type NilCompare added in v1.0.0

type NilCompare struct{}

NilCompare detects situations like

assert.Equal(t, nil, value)
assert.EqualValues(t, nil, value)
assert.Exactly(t, nil, value)

assert.NotEqual(t, nil, value)
assert.NotEqualValues(t, nil, value)

and requires

assert.Nil(t, value)
assert.NotNil(t, value)

func NewNilCompare added in v1.0.0

func NewNilCompare() NilCompare

NewNilCompare constructs NilCompare checker.

func (NilCompare) Check added in v1.0.0

func (checker NilCompare) Check(pass *analysis.Pass, call *CallMeta) *analysis.Diagnostic

func (NilCompare) Name added in v1.0.0

func (NilCompare) Name() string

type RegularChecker

type RegularChecker interface {
	Checker
	Check(pass *analysis.Pass, call *CallMeta) *analysis.Diagnostic
}

RegularChecker check assertion call presented in CallMeta form.

type RequireError

type RequireError struct {
	// contains filtered or unexported fields
}

RequireError detects error assertions like

assert.Error(t, err) // s.Error(err), s.Assert().Error(err)
assert.ErrorIs(t, err, io.EOF)
assert.ErrorAs(t, err, &target)
assert.EqualError(t, err, "end of file")
assert.ErrorContains(t, err, "end of file")
assert.NoError(t, err)
assert.NotErrorIs(t, err, io.EOF)

and requires

require.Error(t, err) // s.Require().Error(err), s.Require().Error(err)
require.ErrorIs(t, err, io.EOF)
require.ErrorAs(t, err, &target)
...

RequireError ignores: - assertion in the `if` condition; - the entire `if-else[-if]` block, if there is an assertion in any `if` condition; - the last assertion in the block, if there are no methods/functions calls after it; - assertions in an explicit goroutine; - assertions in an explicit testing cleanup function or suite teardown methods; - sequence of NoError assertions.

func NewRequireError

func NewRequireError() *RequireError

NewRequireError constructs RequireError checker.

func (RequireError) Check

func (checker RequireError) Check(pass *analysis.Pass, inspector *inspector.Inspector) []analysis.Diagnostic

func (RequireError) Name

func (RequireError) Name() string

func (*RequireError) SetFnPattern added in v1.0.0

func (checker *RequireError) SetFnPattern(p *regexp.Regexp) *RequireError

type SuiteDontUsePkg

type SuiteDontUsePkg struct{}

SuiteDontUsePkg detects situation like

func (s *MySuite) TestSomething() {
	assert.Equal(s.T(), 42, value)
}

and requires

func (s *MySuite) TestSomething() {
	s.Equal(42, value)
}

func NewSuiteDontUsePkg

func NewSuiteDontUsePkg() SuiteDontUsePkg

NewSuiteDontUsePkg constructs SuiteDontUsePkg checker.

func (SuiteDontUsePkg) Check

func (checker SuiteDontUsePkg) Check(pass *analysis.Pass, call *CallMeta) *analysis.Diagnostic

func (SuiteDontUsePkg) Name

func (SuiteDontUsePkg) Name() string

type SuiteExtraAssertCall

type SuiteExtraAssertCall struct {
	// contains filtered or unexported fields
}

SuiteExtraAssertCall detects situation like

func (s *MySuite) TestSomething() {
	s.Assert().Equal(42, value)
}

and requires

func (s *MySuite) TestSomething() {
	s.Equal(42, value)
}

or vice versa (depending on the configurable mode).

func NewSuiteExtraAssertCall

func NewSuiteExtraAssertCall() *SuiteExtraAssertCall

NewSuiteExtraAssertCall constructs SuiteExtraAssertCall checker.

func (SuiteExtraAssertCall) Check

func (checker SuiteExtraAssertCall) Check(pass *analysis.Pass, call *CallMeta) *analysis.Diagnostic

func (SuiteExtraAssertCall) Name

func (*SuiteExtraAssertCall) SetMode

type SuiteExtraAssertCallMode

type SuiteExtraAssertCallMode int

SuiteExtraAssertCallMode reflects different modes of work of SuiteExtraAssertCall checker.

const (
	SuiteExtraAssertCallModeRemove SuiteExtraAssertCallMode = iota
	SuiteExtraAssertCallModeRequire
)

type SuiteTHelper

type SuiteTHelper struct{}

SuiteTHelper requires t.Helper() call in suite helpers:

func (s *RoomSuite) assertRoomRound(roundID RoundID) {
	s.T().Helper()
	s.Equal(roundID, s.getRoom().CurrentRound.ID)
}

func NewSuiteTHelper

func NewSuiteTHelper() SuiteTHelper

NewSuiteTHelper constructs SuiteTHelper checker.

func (SuiteTHelper) Check

func (checker SuiteTHelper) Check(pass *analysis.Pass, inspector *inspector.Inspector) (diagnostics []analysis.Diagnostic)

func (SuiteTHelper) Name

func (SuiteTHelper) Name() string

type UselessAssert added in v1.1.0

type UselessAssert struct{}

UselessAssert detects useless asserts like

1) Asserting of the same variable

assert.Equal(t, tt.value, tt.value)
assert.ElementsMatch(t, users, users)
...

2) Open for contribution...

func NewUselessAssert added in v1.1.0

func NewUselessAssert() UselessAssert

NewUselessAssert constructs UselessAssert checker.

func (UselessAssert) Check added in v1.1.0

func (checker UselessAssert) Check(pass *analysis.Pass, call *CallMeta) *analysis.Diagnostic

func (UselessAssert) Name added in v1.1.0

func (UselessAssert) Name() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL