Skip to content

Commit

Permalink
New linter testifylint
Browse files Browse the repository at this point in the history
  • Loading branch information
Antonboom committed Oct 4, 2023
1 parent dafe146 commit b6ac66c
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 0 deletions.
32 changes: 32 additions & 0 deletions .golangci.reference.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1882,6 +1882,36 @@ linters-settings:
# Default: false
all: false

testifylint:
# Enable all checkers.
# Default: false
enable-all: true
# Enable specific checkers.
# https://github.com/Antonboom/testifylint#checkers
enable:
# Enabled by default:
- bool-compare
- compares
- empty
- error-is-as
- error-nil
- expected-actual
- float-compare
- len
- require-error
- suite-dont-use-pkg
- suite-extra-assert-call
# Disabled by default:
- suite-thelper
expected-actual:
# Regexp for expected variable name.
# Default: (^(exp(ected)?|want(ed)?)([A-Z]\w*)?$)|(^(\w*[a-z])?(Exp(ected)?|Want(ed)?)$)
pattern: ^expected
suite-extra-assert-call:
# To require or remove extra Assert() call?
# Default: remove
mode: require

testpackage:
# Regexp pattern to skip files.
# Default: "(export|internal)_test\\.go"
Expand Down Expand Up @@ -2242,6 +2272,7 @@ linters:
- tagliatelle
- tenv
- testableexamples
- testifylint
- testpackage
- thelper
- tparallel
Expand Down Expand Up @@ -2356,6 +2387,7 @@ linters:
- tagliatelle
- tenv
- testableexamples
- testifylint
- testpackage
- thelper
- tparallel
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ require (
github.com/Abirdcfly/dupword v0.0.13
github.com/Antonboom/errname v0.1.12
github.com/Antonboom/nilnil v0.1.7
github.com/Antonboom/testifylint v0.2.3
github.com/BurntSushi/toml v1.3.2
github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24
github.com/GaijinEntertainment/go-exhaustruct/v3 v3.1.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions pkg/config/linters_settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ type LintersSettings struct {
Stylecheck StaticCheckSettings
TagAlign TagAlignSettings
Tagliatelle TagliatelleSettings
Testifylint TestifylintSettings
Tenv TenvSettings
Testpackage TestpackageSettings
Thelper ThelperSettings
Expand Down Expand Up @@ -737,6 +738,19 @@ type TagliatelleSettings struct {
}
}

type TestifylintSettings struct {
EnableAll bool `mapstructure:"enable-all"`
EnabledCheckers []string `mapstructure:"enable"`

ExpectedActual struct {
ExpVarPattern string `mapstructure:"pattern"`
} `mapstructure:"expected-actual"`

SuiteExtraAssertCall struct {
Mode string `mapstructure:"mode"`
} `mapstructure:"suite-extra-assert-call"`
}

type TestpackageSettings struct {
SkipRegexp string `mapstructure:"skip-regexp"`
AllowPackages []string `mapstructure:"allow-packages"`
Expand Down
36 changes: 36 additions & 0 deletions pkg/golinters/testifylint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package golinters

import (
"github.com/Antonboom/testifylint/analyzer"
"golang.org/x/tools/go/analysis"

"github.com/golangci/golangci-lint/pkg/config"
"github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
)

func NewTestifylint(settings *config.TestifylintSettings) *goanalysis.Linter {
a := analyzer.New()

cfg := make(map[string]map[string]any)
if settings != nil {
cfg[a.Name] = map[string]any{
"enable-all": settings.EnableAll,
}
if len(settings.EnabledCheckers) > 0 {
cfg[a.Name]["enable"] = settings.EnabledCheckers
}
if p := settings.ExpectedActual.ExpVarPattern; p != "" {
cfg[a.Name]["expected-actual.pattern"] = p
}
if m := settings.SuiteExtraAssertCall.Mode; m != "" {
cfg[a.Name]["suite-extra-assert-call.mode"] = m
}
}

return goanalysis.NewLinter(
a.Name,
a.Doc,
[]*analysis.Analyzer{a},
cfg,
).WithLoadMode(goanalysis.LoadModeTypesInfo)
}
8 changes: 8 additions & 0 deletions pkg/lint/lintersdb/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
tagalignCfg *config.TagAlignSettings
tagliatelleCfg *config.TagliatelleSettings
tenvCfg *config.TenvSettings
testifylintCfg *config.TestifylintSettings
testpackageCfg *config.TestpackageSettings
thelperCfg *config.ThelperSettings
unparamCfg *config.UnparamSettings
Expand Down Expand Up @@ -213,6 +214,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
tagalignCfg = &m.cfg.LintersSettings.TagAlign
tagliatelleCfg = &m.cfg.LintersSettings.Tagliatelle
tenvCfg = &m.cfg.LintersSettings.Tenv
testifylintCfg = &m.cfg.LintersSettings.Testifylint
testpackageCfg = &m.cfg.LintersSettings.Testpackage
thelperCfg = &m.cfg.LintersSettings.Thelper
unparamCfg = &m.cfg.LintersSettings.Unparam
Expand Down Expand Up @@ -788,6 +790,12 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
WithPresets(linter.PresetTest).
WithURL("https://github.com/maratori/testableexamples"),

linter.NewConfig(golinters.NewTestifylint(testifylintCfg)).
WithSince("v1.55.0").
WithPresets(linter.PresetTest, linter.PresetBugs).
WithLoadForGoAnalysis().
WithURL("https://github.com/Antonboom/testifylint"),

linter.NewConfig(golinters.NewTestpackage(testpackageCfg)).
WithSince("v1.25.0").
WithPresets(linter.PresetStyle, linter.PresetTest).
Expand Down
62 changes: 62 additions & 0 deletions test/testdata/testifylint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//golangcitest:args -Etestifylint
package testdata

import (
"io"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
)

func TestTestifylint(t *testing.T) {
var (
predicate bool
resultInt int
resultFloat float64
arr []string
err error
)

assert.Equal(t, predicate, true) // want "bool-compare: use assert\\.True"
assert.True(t, resultInt == 1) // want "compares: use assert\\.Equal"
assert.Equal(t, len(arr), 0) // want "empty: use assert\\.Empty"
assert.Error(t, err, io.EOF) // want "error-is-as: invalid usage of assert\\.Error, use assert\\.ErrorIs instead"
assert.Nil(t, err) // want "error-nil: use assert\\.NoError"
assert.Equal(t, resultInt, 42) // want "expected-actual: need to reverse actual and expected values"
assert.Equal(t, resultFloat, 42.42) // want "float-compare: use assert\\.InEpsilon \\(or InDelta\\)"
assert.Equal(t, len(arr), 10) // want "len: use assert\\.Len"

assert.True(t, predicate)
assert.Equal(t, resultInt, 1) // want "expected-actual: need to reverse actual and expected values"
assert.Empty(t, arr)
assert.ErrorIs(t, err, io.EOF) // want "require-error: for error assertions use require"
assert.NoError(t, err) // want "require-error: for error assertions use require"
assert.Equal(t, 42, resultInt)
assert.InEpsilon(t, 42.42, resultFloat, 0.0001)
assert.Len(t, arr, 10)

require.ErrorIs(t, err, io.EOF)
require.NoError(t, err)

t.Run("formatted", func(t *testing.T) {
assert.Equal(t, predicate, true, "message") // want "bool-compare: use assert\\.True"
assert.Equal(t, predicate, true, "message %d", 42) // want "bool-compare: use assert\\.True"
assert.Equalf(t, predicate, true, "message") // want "bool-compare: use assert\\.Truef"
assert.Equalf(t, predicate, true, "message %d", 42) // want "bool-compare: use assert\\.Truef"
})
}

type SuiteExample struct {
suite.Suite
}

func TestSuiteExample(t *testing.T) {
suite.Run(t, new(SuiteExample))
}

func (s *SuiteExample) TestAll() {
var b bool
s.Assert().True(b) // want "suite-extra-assert-call: need to simplify the assertion to s\\.True"
}

0 comments on commit b6ac66c

Please sign in to comment.