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

Config: disable & disable-all #20

Merged
merged 1 commit into from
Oct 29, 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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 26 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,37 @@ and [2022](https://www.jetbrains.com/lp/devecosystem-2022/go/#which-testing-fram
```
$ go install github.com/Antonboom/testifylint@latest
$ testifylint -h
$ testifylint ./...
$ testifylint -fix ./...
```

## Configuring

### CLI

```bash
# Use default checkers
$ testifylint ./...

# Enable checkers in addition to enabled by default checkers
$ testifylint --enable=require-error,empty ./...

# Disable checkers from enabled by default checkers
$ testifylint --disable=require-error,empty ./...

# Enable some checkers only
$ testifylint --disable-all --enable=require-error,empty ./...

# Disable some checkers only
$ testifylint --enable-all --disable=require-error,empty ./...

# Checker specific settings
$ testifylint --suite-extra-assert-call.mode=require ./...
$ testifylint --expected-actual.pattern=^wanted$ ./...
```
$ testifylint --enable-all ./...
$ testifylint --enable=empty,error-is-as ./...
$ testifylint --enable=expected-actual --expected-actual.pattern=^wanted$ ./...
$ testifylint --enable=suite-extra-assert-call --suite-extra-assert-call.mode=require ./...
```

### golangci-lint

https://golangci-lint.run/usage/linters/#testifylint

## Checkers

Expand Down
10 changes: 8 additions & 2 deletions analyzer/analyzer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,20 @@ func TestTestifyLint(t *testing.T) {
}{
{
dir: "base-test",
flags: map[string]string{"enable": checkers.NewBoolCompare().Name()},
flags: map[string]string{"disable-all": "true", "enable": checkers.NewBoolCompare().Name()},
},
{
dir: "checkers-priority",
flags: map[string]string{"enable-all": "true"},
},
{
dir: "error-as-target",
flags: map[string]string{"enable": checkers.NewErrorIsAs().Name()},
flags: map[string]string{"disable-all": "true", "enable": checkers.NewErrorIsAs().Name()},
},
{
dir: "expected-var-custom-pattern",
flags: map[string]string{
"disable-all": "true",
"enable": checkers.NewExpectedActual().Name(),
"expected-actual.pattern": "goldenValue",
},
Expand All @@ -43,6 +44,7 @@ func TestTestifyLint(t *testing.T) {
{
dir: "suite-require-extra-assert-call",
flags: map[string]string{
"disable-all": "true",
"enable": checkers.NewSuiteExtraAssertCall().Name(),
"suite-extra-assert-call.mode": "require",
},
Expand Down Expand Up @@ -76,9 +78,13 @@ func TestTestifyLint_CheckersDefault(t *testing.T) {
t.Parallel()

anlzr := analyzer.New()
if err := anlzr.Flags.Set("disable-all", "true"); err != nil {
t.Fatal(err)
}
if err := anlzr.Flags.Set("enable", checker); err != nil {
t.Fatal(err)
}

pkg := filepath.Join("checkers-default", checker)
analysistest.RunWithSuggestedFixes(t, analysistest.TestData(), anlzr, pkg)
})
Expand Down
28 changes: 24 additions & 4 deletions analyzer/checkers_factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,34 @@ import (

// newCheckers accepts linter config and returns slices of enabled checkers sorted by priority.
func newCheckers(cfg config.Config) ([]checkers.RegularChecker, []checkers.AdvancedChecker, error) {
enabledCheckers := cfg.EnabledCheckers
if len(enabledCheckers) == 0 {
enabledCheckers = checkers.EnabledByDefault()
if err := cfg.Validate(); err != nil {
return nil, nil, err
}

enabledCheckersSet := make(map[string]struct{})

if cfg.EnableAll {
enabledCheckers = checkers.All()
for _, checker := range checkers.All() {
enabledCheckersSet[checker] = struct{}{}
}
} else if !cfg.DisableAll {
for _, checker := range checkers.EnabledByDefault() {
enabledCheckersSet[checker] = struct{}{}
}
}

for _, checker := range cfg.EnabledCheckers {
enabledCheckersSet[checker] = struct{}{}
}

for _, checker := range cfg.DisabledCheckers {
delete(enabledCheckersSet, checker)
}

enabledCheckers := make([]string, 0, len(enabledCheckersSet))
for v := range enabledCheckersSet {
enabledCheckers = append(enabledCheckers, v)
}
checkers.SortByPriority(enabledCheckers)

regularCheckers := make([]checkers.RegularChecker, 0, len(enabledCheckers))
Expand Down
102 changes: 72 additions & 30 deletions analyzer/checkers_factory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ func Test_newCheckers(t *testing.T) {
checkers.NewSuiteDontUsePkg(),
}

enabledByDefaultAdvancedCheckers := []checkers.AdvancedChecker{}
allAdvancedCheckers := []checkers.AdvancedChecker{
checkers.NewSuiteTHelper(),
}

cases := []struct {
name string
cfg config.Config
Expand All @@ -51,65 +56,83 @@ func Test_newCheckers(t *testing.T) {
name: "no config",
cfg: config.Config{},
expRegular: enabledByDefaultRegularCheckers,
expAdvanced: []checkers.AdvancedChecker{},
expAdvanced: enabledByDefaultAdvancedCheckers,
},
{
name: "no enabled checkers",
cfg: config.Config{
EnabledCheckers: []string{},
},
name: "default config",
cfg: config.NewDefault(),
expRegular: enabledByDefaultRegularCheckers,
expAdvanced: []checkers.AdvancedChecker{},
expAdvanced: enabledByDefaultAdvancedCheckers,
},
{
name: "no enabled checkers but enable-all true",
cfg: config.Config{
EnabledCheckers: []string{},
EnableAll: true,
},
expRegular: allRegularCheckers,
expAdvanced: []checkers.AdvancedChecker{
checkers.NewSuiteTHelper(),
},
},
{
name: "enabled checkers defined",
name: "enable two checkers only",
cfg: config.Config{
DisableAll: true,
EnabledCheckers: config.KnownCheckersValue{
checkers.NewSuiteTHelper().Name(),
checkers.NewRequireError().Name(),
checkers.NewSuiteExtraAssertCall().Name(),
checkers.NewLen().Name(),
},
},
expRegular: []checkers.RegularChecker{
checkers.NewLen(),
checkers.NewRequireError(),
checkers.NewSuiteExtraAssertCall(),
},
expAdvanced: []checkers.AdvancedChecker{
checkers.NewSuiteTHelper(),
expAdvanced: []checkers.AdvancedChecker{},
},
{
name: "disable two checkers only",
cfg: config.Config{
EnableAll: true,
DisabledCheckers: config.KnownCheckersValue{
checkers.NewRequireError().Name(),
checkers.NewSuiteTHelper().Name(),
},
},
expRegular: filter(allRegularCheckers, config.KnownCheckersValue{
checkers.NewRequireError().Name(),
checkers.NewSuiteTHelper().Name(),
}),
expAdvanced: filter(allAdvancedCheckers, config.KnownCheckersValue{
checkers.NewRequireError().Name(),
checkers.NewSuiteTHelper().Name(),
}),
},
{
name: "enabled checkers defined but enable-all true",
name: "enable one checker in addition to enabled by default checkers",
cfg: config.Config{
EnabledCheckers: config.KnownCheckersValue{
checkers.NewSuiteTHelper().Name(),
checkers.NewRequireError().Name(),
checkers.NewSuiteExtraAssertCall().Name(),
checkers.NewLen().Name(),
},
EnableAll: true,
},
expRegular: allRegularCheckers,
expAdvanced: []checkers.AdvancedChecker{
checkers.NewSuiteTHelper(),
},
},
{
name: "disable three checkers from enabled by default checkers",
cfg: config.Config{
DisabledCheckers: config.KnownCheckersValue{
checkers.NewNilCompare().Name(),
checkers.NewErrorNil().Name(),
checkers.NewRequireError().Name(),
},
},
expRegular: filter(enabledByDefaultRegularCheckers, config.KnownCheckersValue{
checkers.NewNilCompare().Name(),
checkers.NewErrorNil().Name(),
checkers.NewRequireError().Name(),
}),
expAdvanced: filter(enabledByDefaultAdvancedCheckers, config.KnownCheckersValue{
checkers.NewNilCompare().Name(),
checkers.NewErrorNil().Name(),
checkers.NewRequireError().Name(),
}),
},
{
name: "expected-actual pattern defined",
cfg: config.Config{
DisableAll: true,
EnabledCheckers: config.KnownCheckersValue{checkers.NewExpectedActual().Name()},
ExpectedActual: config.ExpectedActualConfig{
ExpVarPattern: config.RegexpValue{Regexp: pattern},
Expand All @@ -123,6 +146,7 @@ func Test_newCheckers(t *testing.T) {
{
name: "suite-extra-assert-call mode defined",
cfg: config.Config{
DisableAll: true,
EnabledCheckers: config.KnownCheckersValue{checkers.NewSuiteExtraAssertCall().Name()},
SuiteExtraAssertCall: config.SuiteExtraAssertCallConfig{
Mode: checkers.SuiteExtraAssertCallModeRequire,
Expand All @@ -143,18 +167,36 @@ func Test_newCheckers(t *testing.T) {
}

if !reflect.DeepEqual(tt.expRegular, rc) {
t.Fatalf("unexpected regular checkers: %#v", rc)
t.Fatalf("unexpected regular checkers: %#v != %#v", rc, tt.expRegular)
}
if !reflect.DeepEqual(tt.expAdvanced, ac) {
t.Fatalf("unexpected expAdvanced checkers: %#v", ac)
t.Fatalf("unexpected expAdvanced checkers: %#v != %#v", ac, tt.expAdvanced)
}
})
}
}

func Test_newCheckers_invalidConfig(t *testing.T) {
_, _, err := newCheckers(config.Config{EnableAll: true, DisableAll: true})
if nil == err {
t.Fatal("no error but expected")
}
}

func Test_newCheckers_unknownChecker(t *testing.T) {
_, _, err := newCheckers(config.Config{EnabledCheckers: config.KnownCheckersValue{"unknown"}})
if nil == err {
t.Fatal("no error but expected")
}
}

func filter[T checkers.Checker](in []T, exclude config.KnownCheckersValue) []T {
result := make([]T, 0)
for _, v := range in {
if exclude.Contains(v.Name()) {
continue
}
result = append(result, v)
}
return result
}
50 changes: 45 additions & 5 deletions internal/config/config.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
package config

import (
"errors"
"flag"
"fmt"

"github.com/Antonboom/testifylint/internal/checkers"
)

// NewDefault builds default testifylint config.
func NewDefault() Config {
return Config{
EnableAll: false,
EnabledCheckers: checkers.EnabledByDefault(),
EnableAll: false,
DisabledCheckers: nil,
DisableAll: false,
EnabledCheckers: nil,
ExpectedActual: ExpectedActualConfig{
ExpVarPattern: RegexpValue{checkers.DefaultExpectedVarPattern},
},
Expand All @@ -22,8 +26,11 @@ func NewDefault() Config {

// Config implements testifylint configuration.
type Config struct {
EnableAll bool
EnabledCheckers KnownCheckersValue
EnableAll bool
DisabledCheckers KnownCheckersValue
DisableAll bool
EnabledCheckers KnownCheckersValue

ExpectedActual ExpectedActualConfig
SuiteExtraAssertCall SuiteExtraAssertCallConfig
}
Expand All @@ -38,10 +45,43 @@ type SuiteExtraAssertCallConfig struct {
Mode checkers.SuiteExtraAssertCallMode
}

func (cfg Config) Validate() error {
if cfg.EnableAll {
if cfg.DisableAll {
return errors.New("enable-all and disable-all options must not be combined")
}

if len(cfg.EnabledCheckers) != 0 {
return errors.New("enable-all and enable options must not be combined")
}
}

if cfg.DisableAll {
if len(cfg.DisabledCheckers) != 0 {
return errors.New("disable-all and disable options must not be combined")
}

if len(cfg.EnabledCheckers) == 0 {
return errors.New("all checkers were disabled, but no one checker was enabled: at least one must be enabled")
}
}

for _, checker := range cfg.DisabledCheckers {
if cfg.EnabledCheckers.Contains(checker) {
return fmt.Errorf("checker %q disabled and enabled at one moment", checker)
}
}

return nil
}

// BindToFlags binds Config fields to according flags.
func BindToFlags(cfg *Config, fs *flag.FlagSet) {
fs.BoolVar(&cfg.EnableAll, "enable-all", false, "enable all checkers")
fs.Var(&cfg.EnabledCheckers, "enable", "comma separated list of enabled checkers")
fs.Var(&cfg.DisabledCheckers, "disable", "comma separated list of disabled checkers (to exclude from enabled by default)")
fs.BoolVar(&cfg.DisableAll, "disable-all", false, "disable all checkers")
fs.Var(&cfg.EnabledCheckers, "enable", "comma separated list of enabled checkers (in addition to enabled by default)")

fs.Var(&cfg.ExpectedActual.ExpVarPattern, "expected-actual.pattern", "regexp for expected variable name")
fs.Var(NewEnumValue(suiteExtraAssertCallModeAsString, &cfg.SuiteExtraAssertCall.Mode),
"suite-extra-assert-call.mode", "to require or remove extra Assert() call")
Expand Down
Loading
Loading