Golang Test
- Don't run
go test ./... unless ask to run all tests explicitly.
- Prefer
go test <pkg> or -run <TestName> over go test ./... (slow).
- Use table-driven tests covering happy path, failure, and edge cases.
- Skip trivial getters/setters unless they contain non-trivial logic.
- Use
testify/assert with assert.*(t, *) or require.*(t, *) directly, not assert.New(t).
- Use
testify/suite for related test groups, and use s.*(*, *) when asserting.
- Use the testify
EXPECT method for mocks; avoid mock.Anything.
- Use
assert.AnError if needed, and assert.Equal for error assertions.
- Assert full maps/structs/slices/arrays, not individual fields.
- Prefer direct value assertions over
mock.MatchedBy; use it only for dynamically-generated args.
- Every mock must use
.Once() or .Times(), only use .Maybe() when necessary; avoid no-op expectations.
- Name tests
Test<FunctionName>_[Optional]; use table style or sub-tests for multiple cases.
- Don't use
assert.* with if statements; use assert.* directly for clarity and better failure messages.
- Use
t.Run() for sub-tests when testing multiple cases for the same function, and use table-driven tests for multiple cases with similar setup/assertions. Avoid writing separate test functions for each case when they share common logic.
- Prefer the simplest test setup that proves behavior; avoid extra helper abstractions/state tracking (e.g., counters/wrappers) unless reused or required by interface constraints.
- The basic table-driven test pattern is:
import (
[system packages]
[third-party packages]
[internal packages]
)
func TestFunction(t *testing.T) {
// The name should start with `mock` to indicate it's a mocked function.
var (
ctx context.Context
mockFunc *mocks.MockedInterface
)
beforeEach := func() {
mockFunc = mocks.NewMockedInterface(t)
}
tests := []struct {
name string
input any
setup func()
expect any
expectError error
}{
{
name: "should do something",
input: someInput,
setup: func() {
mockFunc.EXPECT().SomeMethod(someArgs).Return(someResult, nil).Once()
},
expect: someResult,
expectError: nil,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
beforeEach()
tt.setup()
result, err := FunctionUnderTest(tt.input)
assert.Equal(t, tt.expect, result)
assert.Equal(t, tt.expectError, err)
})
}
}
1---2name: goravel-testing3description: Goravel test-writing and test-running conventions. Use this skill when adding, updating, reviewing, or running tests in Goravel repositories.4---56# Golang Test78- Don't run `go test ./...` unless ask to run all tests explicitly.9- Prefer `go test <pkg>` or `-run <TestName>` over `go test ./...` (slow).10- Use table-driven tests covering happy path, failure, and edge cases.11- Skip trivial getters/setters unless they contain non-trivial logic.12- Use `testify/assert` with `assert.*(t, *)` or `require.*(t, *)` directly, not `assert.New(t)`.13- Use `testify/suite` for related test groups, and use `s.*(*, *)` when asserting.14- Use the testify `EXPECT` method for mocks; avoid `mock.Anything`.15- Use `assert.AnError` if needed, and `assert.Equal` for error assertions.16- Assert full maps/structs/slices/arrays, not individual fields.17- Prefer direct value assertions over `mock.MatchedBy`; use it only for dynamically-generated args.18- Every mock must use `.Once()` or `.Times()`, only use `.Maybe()` when necessary; avoid no-op expectations.19- Name tests `Test<FunctionName>_[Optional]`; use table style or sub-tests for multiple cases.20- Don't use `assert.*` with `if` statements; use `assert.*` directly for clarity and better failure messages.21- Use `t.Run()` for sub-tests when testing multiple cases for the same function, and use table-driven tests for multiple cases with similar setup/assertions. Avoid writing separate test functions for each case when they share common logic.22- Prefer the simplest test setup that proves behavior; avoid extra helper abstractions/state tracking (e.g., counters/wrappers) unless reused or required by interface constraints.23- The basic table-driven test pattern is:2425```go26import (27 [system packages]2829 [third-party packages]3031 [internal packages]32)3334func TestFunction(t *testing.T) {35 // The name should start with `mock` to indicate it's a mocked function.36 var (37 ctx context.Context38 mockFunc *mocks.MockedInterface39 )4041 beforeEach := func() {42 mockFunc = mocks.NewMockedInterface(t)43 }4445 tests := []struct {46 name string47 input any48 setup func()49 expect any50 expectError error51 }{52 {53 name: "should do something",54 input: someInput,55 setup: func() {56 mockFunc.EXPECT().SomeMethod(someArgs).Return(someResult, nil).Once()57 },58 expect: someResult,59 expectError: nil,60 },61 }6263 for _, tt := range tests {64 t.Run(tt.name, func(t *testing.T) {65 beforeEach()66 tt.setup()6768 result, err := FunctionUnderTest(tt.input)69 assert.Equal(t, tt.expect, result)70 assert.Equal(t, tt.expectError, err)71 })72 }73}74```