Skip to content

manuelarte/testcomments

Repository files navigation

Test Comments Lint

CI Go Report Card version

Go Lint that follows standards described in TestComments.

⬇️ Getting Started

To install it, run:

go install github.com/manuelarte/testcomments@latest

And then use it with

testcomments [-equality-comparison.reflect=true|false] [-equality-comparison.equal=true|false]
[-got-before-want=true|false] [-identify-function=true|false]
[-table-driven-format.type=map|slice] [-table-driven-format.inlined=true|false] ./...

Parameters:

  • equality-comparison.reflect: true|false (default true) Checks reflect.DeepEqual can be replaced by newer cmp.Equal.
  • equality-comparison.equal: true|false (default true) Checks helper test functions to compare two structs that can be replaced by either cmp.Equal or cmp.Diff.
  • got-before-want: true|false (default true) Check that the failure message outputs the actual value that the function returned before printing the value that was expected.
  • identify-function: true|false (default true) Check that the failure messages in t.Errorf contains the function name.
  • table-driven-format.type: map|slice (default ``) Check that the table-driven tests are either Map or Slice, empty to leave it as it is.
  • table-driven-format.inlined: true|false (default false) Check that the table-driven tests are inlined in the for loop.

🚀 Features

Equality Comparison

This linter detects the expression:

if !reflect.DeepEqual(got, want) {
    t.Errorf("MyFunction got %v, want %v", got, want)
}

And lint that the newer cmp.Equal or cmp.Diff should be used. For more use cases and examples, check equality-comparison.

Note

Suggested Fix can't be supported since it could potentially imply adding go-cmp dependency and reflect.DeepEqual can't be directly replaced by cmp.Equal or cmp.Diff.

Equal

This linter detects helper functions like:

func areEqual(a, b MyStruct) bool {
 return a.Name && b.Name && a.Surname == b.Surname
}

And propose to use cmp.Equal or cmp.Diff.

Test outputs should output the actual value that the function returned before printing the value that was expected. So prefer failure messages like YourFunc(%v) = %v, want %v over want: %v, got: %v.

Note

Suggested Fix can't be supported since it would imply changing the original failure message.

In most tests, failure messages should include the name of the function that failed, even though it seems obvious from the name of the test function.

Prefer:

t.Errorf("YourFunc(%v) = %v, want %v", in, got, want)

and not:

t.Errorf("got %v, want %v", got, want)

Note

Suggested Fix may be supported.

Table-Driven Test Format

Feature that checks consistency when declaring your table-driven tests. The options are:

Map non-inlined

tests := map[string]struct {
	in int
	out int
} {
	"test1": {
		in: 1,
		out: 1,
	},
}
for name, test := range tests {
	t.Run(name, func(t *testing.T) {
		got := abs(test.in)
		if got != test.out {
			t.Errorf("abs(%d) = %d, want %d", test.in, got, test.out)
		}
	})
}

Map inlined

for name, test := range map[string]struct {
	in int
	out int
} {
	"test1": {
		in: 1,
		out: 1,
	},
} {
	t.Run(name, func(t *testing.T) {
		got := abs(test.in)
		if got != test.out {
			t.Errorf("abs(%d) = %d, want %d", test.in, got, test.out)
		}
	})
}

Slice non-inlined

tests := []struct {
	name string
	in int
	out int
} {
	{
		name: "test1",
		in: 1,
		out: 1,
	},
}
for _, test := range tests {
	t.Run(test.name, func(t *testing.T) {
		got := abs(test.in)
		if got != test.out {
			t.Errorf("abs(%d) = %d, want %d", test.in, got, test.out)
		}
	})
}

Slice inlined

for _, test := range []struct {
	name string
	in int
	out int
} {
	{
		name: "test1",
		in: 1,
		out: 1,
	},
} {
	t.Run(test.name, func(t *testing.T) {
		got := abs(test.in)
		if got != test.out {
			t.Errorf("abs(%d) = %d, want %d", test.in, got, test.out)
		}
	})
}

About

Go Linter 🧐 that follows https://go.dev/wiki/TestComments

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors