github.com/grafana/pyroscope@v1.18.0/.cursor/rules/go-testing.mdc (about) 1 --- 2 description: Go testing standards and patterns for Pyroscope 3 globs: 4 - "**/*_test.go" 5 --- 6 7 # Go Testing Standards 8 9 ## Test File Naming 10 11 - Test files: `*_test.go` 12 - Test function naming: `TestFunctionName` or `TestComponentName_Method` 13 14 ## Test Structure 15 16 Use table-driven tests for multiple cases: 17 18 ```go 19 func TestDistributor_Push(t *testing.T) { 20 t.Parallel() 21 22 tests := []struct { 23 name string 24 input *pushv1.PushRequest 25 wantErr bool 26 }{ 27 {name: "valid request", input: validRequest(), wantErr: false}, 28 {name: "invalid tenant", input: invalidRequest(), wantErr: true}, 29 } 30 31 for _, tt := range tests { 32 t.Run(tt.name, func(t *testing.T) { 33 d := setupDistributor(t) 34 err := d.Push(context.Background(), tt.input) 35 if tt.wantErr { 36 require.Error(t, err) 37 } else { 38 require.NoError(t, err) 39 } 40 }) 41 } 42 } 43 ``` 44 45 ## Assertions 46 47 - Use `require` for fatal assertions (test stops on failure) 48 - Use `assert` for non-fatal assertions (test continues) 49 50 ```go 51 import ( 52 "github.com/stretchr/testify/assert" 53 "github.com/stretchr/testify/require" 54 ) 55 56 // Fatal - stops test immediately 57 require.NoError(t, err) 58 require.NotNil(t, result) 59 60 // Non-fatal - continues test 61 assert.Equal(t, expected, actual) 62 ``` 63 64 ## Test Organization 65 66 1. **Subtests**: Use `t.Run()` for grouping related cases 67 2. **Parallel Tests**: Use `t.Parallel()` when tests are independent 68 3. **Cleanup**: Always use `t.Cleanup()` for resource cleanup 69 70 ```go 71 func TestComponent(t *testing.T) { 72 t.Parallel() 73 74 resource := createResource(t) 75 t.Cleanup(func() { 76 resource.Close() 77 }) 78 79 t.Run("subtest", func(t *testing.T) { 80 // test logic 81 }) 82 } 83 ``` 84 85 ## Test Data 86 87 - Store test data in `testdata/` directories 88 - Use relative paths from the test file 89 90 ## Integration Tests 91 92 Use build tags for integration tests: 93 94 ```go 95 //go:build integration 96 97 package mypackage_test 98 99 func TestIntegration(t *testing.T) { 100 // ... 101 } 102 ``` 103 104 ## Mocking 105 106 - Use `mockery` for generating mocks from interfaces 107 - Place mocks in appropriate locations based on scope 108 109 ## Multi-tenancy Testing 110 111 **Always test with multiple tenants** to catch isolation issues: 112 113 ```go 114 func TestMultiTenant(t *testing.T) { 115 tenants := []string{"tenant-a", "tenant-b"} 116 117 for _, tenant := range tenants { 118 t.Run(tenant, func(t *testing.T) { 119 ctx := tenant.InjectTenantID(context.Background(), tenant) 120 // verify tenant isolation 121 }) 122 } 123 } 124 ``` 125 126 ## Running Tests 127 128 ```bash 129 # Run all tests 130 make go/test 131 132 # Run specific package tests 133 go test ./pkg/distributor/... 134 135 # Run with race detector 136 go test -race ./... 137 138 # Run benchmarks 139 go test -bench=. ./pkg/... 140 ```