From eda67efb61b8c72df17f7f77eebae221d03f9080 Mon Sep 17 00:00:00 2001 From: Nathan Nutter Date: Thu, 5 Nov 2026 00:46:38 -0600 Subject: [PATCH] Integrate the testifylint analyzer testify has no type-level check for a misuse such as assert.True on a comparison, and testifylint reports it. Its analyzer needs the inspect analyzer, which the driver already supplies for the analyzer graph. analysistest loads testdata in GOPATH mode, where the real testify module is not reachable. The testdata holds a stub of the assert package under the import path that testifylint matches. The stub carries the calls the testdata makes, so the test needs no network and no module file. Change-Id: I67d235f00fe3e741dc1fc89ac213b97deb3003d3 --- cmd/constable/main.go | 2 ++ go.mod | 1 + go.sum | 2 ++ .../github.com/stretchr/testify/assert/assert.go | 15 +++++++++++++++ .../analysis/testifylint/testdata/src/t/t.go | 11 +++++++++++ .../testifylint/testdata/src/t/zz_generated.go | 13 +++++++++++++ internal/analysis/testifylint/testifylint.go | 16 ++++++++++++++++ .../analysis/testifylint/testifylint_test.go | 13 +++++++++++++ 8 files changed, 73 insertions(+) create mode 100644 internal/analysis/testifylint/testdata/src/github.com/stretchr/testify/assert/assert.go create mode 100644 internal/analysis/testifylint/testdata/src/t/t.go create mode 100644 internal/analysis/testifylint/testdata/src/t/zz_generated.go create mode 100644 internal/analysis/testifylint/testifylint.go create mode 100644 internal/analysis/testifylint/testifylint_test.go diff --git a/cmd/constable/main.go b/cmd/constable/main.go index f732742..00c45b7 100644 --- a/cmd/constable/main.go +++ b/cmd/constable/main.go @@ -8,6 +8,7 @@ import ( "github.com/nnutter/constable/internal/analysis/predicates" "github.com/nnutter/constable/internal/analysis/sumtype" "github.com/nnutter/constable/internal/analysis/testify" + "github.com/nnutter/constable/internal/analysis/testifylint" "github.com/nnutter/constable/internal/driver" ) @@ -26,5 +27,6 @@ func main() { complexity.Analyzer, errcheck.Analyzer, sumtype.Analyzer, + testifylint.Analyzer, ) } diff --git a/go.mod b/go.mod index a736bb3..67a2278 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.27.3 require ( github.com/alecthomas/go-check-sumtype v0.5.0 github.com/kisielk/errcheck v1.30.0 + github.com/nnutter/testifylint v0.0.1 github.com/stretchr/testify v1.12.1 golang.org/x/tools v0.52.0 ) diff --git a/go.sum b/go.sum index 0f56789..642c552 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,8 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/kisielk/errcheck v1.30.0 h1:ZIxNDAfAd4larXHTceoZP/dYPAB90dHg1OYhA2sVh5k= github.com/kisielk/errcheck v1.30.0/go.mod h1:uiCAInmFuyOje4VDdbQSP9mgqf5gORYSXrDf19XilsI= +github.com/nnutter/testifylint v0.0.1 h1:QhFq2HgC7LxnaG5Z1Gi4aYN42y+fywfMY+e9xTYe0WM= +github.com/nnutter/testifylint v0.0.1/go.mod h1:DvNLVJQrA3YfswHJxaGzitfYt2gxFzlIs29buaH8sP4= github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE= github.com/stretchr/testify v1.12.1/go.mod h1:MDEgiDPPsNp5cuIrHPPCyornHKgEVbtFUmoNlxoYthg= go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw= diff --git a/internal/analysis/testifylint/testdata/src/github.com/stretchr/testify/assert/assert.go b/internal/analysis/testifylint/testdata/src/github.com/stretchr/testify/assert/assert.go new file mode 100644 index 0000000..31902b9 --- /dev/null +++ b/internal/analysis/testifylint/testdata/src/github.com/stretchr/testify/assert/assert.go @@ -0,0 +1,15 @@ +// Package assert is a stub of github.com/stretchr/testify/assert that holds +// the calls the testdata makes. analysistest loads testdata in GOPATH mode, so +// the testdata cannot import the real module. +package assert + +// TestingT is the part of testing.T that the assertions use. +type TestingT interface { + Errorf(format string, args ...any) +} + +// True asserts that value is true. +func True(t TestingT, value bool, msgAndArgs ...any) bool { return value } + +// NotEqual asserts that expected and actual are not equal. +func NotEqual(t TestingT, expected, actual any, msgAndArgs ...any) bool { return true } diff --git a/internal/analysis/testifylint/testdata/src/t/t.go b/internal/analysis/testifylint/testdata/src/t/t.go new file mode 100644 index 0000000..3323833 --- /dev/null +++ b/internal/analysis/testifylint/testdata/src/t/t.go @@ -0,0 +1,11 @@ +package t + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestCompare(t *testing.T) { + assert.True(t, 1 != 2) // want `compares: use assert.NotEqual` +} diff --git a/internal/analysis/testifylint/testdata/src/t/zz_generated.go b/internal/analysis/testifylint/testdata/src/t/zz_generated.go new file mode 100644 index 0000000..2e2eda8 --- /dev/null +++ b/internal/analysis/testifylint/testdata/src/t/zz_generated.go @@ -0,0 +1,13 @@ +// Code generated by hand. DO NOT EDIT. + +package t + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestGenerated(t *testing.T) { + assert.True(t, 1 != 2) +} diff --git a/internal/analysis/testifylint/testifylint.go b/internal/analysis/testifylint/testifylint.go new file mode 100644 index 0000000..31539e6 --- /dev/null +++ b/internal/analysis/testifylint/testifylint.go @@ -0,0 +1,16 @@ +// Package testifylint adapts the testifylint analyzer to constable. +// +// constable embeds the analyzer from another module instead of reimplementing +// it, so this package holds the places where constable's own policy differs +// from the upstream default. +package testifylint + +import ( + "github.com/nnutter/testifylint/analyzer" + + "github.com/nnutter/constable/internal/generated" +) + +// Analyzer reports tests that misuse testify. It is the upstream analyzer with +// constable's generated-file policy applied. +var Analyzer = generated.Skip(analyzer.New()) diff --git a/internal/analysis/testifylint/testifylint_test.go b/internal/analysis/testifylint/testifylint_test.go new file mode 100644 index 0000000..ef4ae5c --- /dev/null +++ b/internal/analysis/testifylint/testifylint_test.go @@ -0,0 +1,13 @@ +package testifylint_test + +import ( + "testing" + + "golang.org/x/tools/go/analysis/analysistest" + + "github.com/nnutter/constable/internal/analysis/testifylint" +) + +func TestAnalyzer(t *testing.T) { + analysistest.Run(t, analysistest.TestData(), testifylint.Analyzer, "t") +}