Skip to content

Commit

Permalink
Config: disable & disable-all
Browse files Browse the repository at this point in the history
  • Loading branch information
Antonboom committed Oct 29, 2023
1 parent e3b8194 commit 0691784
Show file tree
Hide file tree
Showing 8 changed files with 355 additions and 69 deletions.
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

0 comments on commit 0691784

Please sign in to comment.