Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add testifylint linter #4103

Merged
merged 2 commits into from
Oct 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
31 changes: 31 additions & 0 deletions .golangci.reference.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1882,6 +1882,35 @@ linters-settings:
# Default: false
all: false

testifylint:
# Enable all checkers.
# Default: false
enable-all: true
# Enable specific checkers.
# https://github.com/Antonboom/testifylint#checkers
# 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"]
enable:
- bool-compare
- compares
- empty
- error-is-as
- error-nil
- expected-actual
- float-compare
- len
- require-error
- suite-dont-use-pkg
- suite-extra-assert-call
- 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 +2271,7 @@ linters:
- tagliatelle
- tenv
- testableexamples
- testifylint
- testpackage
- thelper
- tparallel
Expand Down Expand Up @@ -2356,6 +2386,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"
}