[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M71EQ3DSMSTEVEZKPXB0P6FE":3,"skill-same:01M71EQ3DSMSTEVEZKPXB0P6FE":71},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":22,"publishedAt":43,"linkOnly":44,"markdownContent":45,"markdownBody":46,"frontMatter":47,"refName":49,"commitSha":50,"skillDirectory":51,"forksCount":52,"repositoryHtmlUrl":53,"repositoryHomepageUrl":6,"ownerHtmlUrl":54,"ownerBlogUrl":6,"ownerDescription":55,"updatedAt":56,"install":57,"resources":70},"01M71EQ3DSMSTEVEZKPXB0P6FE","golang-testing",null,"Go testing patterns including table-driven tests, subtests, benchmarks, fuzzing, and test coverage. Follows TDD methodology with idiomatic Go practices.","ViewWay\u002Fhermes-by-everythings","ViewWay","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F57283862?v=4","01M71ENR60K309MXA64A23SEW5","01M71ENR6QYM7NQHP29W53HSXT",3,"MIT","https:\u002F\u002Fgithub.com\u002FViewWay\u002Fhermes-by-everythings\u002Fblob\u002Fmain\u002Fskills\u002Fgolang-testing\u002FSKILL.md",[17],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000008","测试与质量","SCENARIO","使用场景",[23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42],"testing","golang","golang testing","driven","methodology","tdd","test","with","benchmarks","fuzzing","tests","idiomatic","idiomatic go","table","patterns","go","test coverage","go testing","testing patterns","coverage","2026-11-10 10:12:30",false,"---\nname: golang-testing\ndescription: Go testing patterns including table-driven tests, subtests, benchmarks, fuzzing, and test coverage. Follows TDD methodology with idiomatic Go practices.\norigin: ECC\n---\n\n# Go Testing Patterns\n\nComprehensive Go testing patterns for writing reliable, maintainable tests following TDD methodology.\n\n## When to Activate\n\n- Writing new Go functions or methods\n- Adding test coverage to existing code\n- Creating benchmarks for performance-critical code\n- Implementing fuzz tests for input validation\n- Following TDD workflow in Go projects\n\n## TDD Workflow for Go\n\n### The RED-GREEN-REFACTOR Cycle\n\n```\nRED     → Write a failing test first\nGREEN   → Write minimal code to pass the test\nREFACTOR → Improve code while keeping tests green\nREPEAT  → Continue with next requirement\n```\n\n### Step-by-Step TDD in Go\n\n```go\n\u002F\u002F Step 1: Define the interface\u002Fsignature\n\u002F\u002F calculator.go\npackage calculator\n\nfunc Add(a, b int) int {\n    panic(\"not implemented\") \u002F\u002F Placeholder\n}\n\n\u002F\u002F Step 2: Write failing test (RED)\n\u002F\u002F calculator_test.go\npackage calculator\n\nimport \"testing\"\n\nfunc TestAdd(t *testing.T) {\n    got := Add(2, 3)\n    want := 5\n    if got != want {\n        t.Errorf(\"Add(2, 3) = %d; want %d\", got, want)\n    }\n}\n\n\u002F\u002F Step 3: Run test - verify FAIL\n\u002F\u002F $ go test\n\u002F\u002F --- FAIL: TestAdd (0.00s)\n\u002F\u002F panic: not implemented\n\n\u002F\u002F Step 4: Implement minimal code (GREEN)\nfunc Add(a, b int) int {\n    return a + b\n}\n\n\u002F\u002F Step 5: Run test - verify PASS\n\u002F\u002F $ go test\n\u002F\u002F PASS\n\n\u002F\u002F Step 6: Refactor if needed, verify tests still pass\n```\n\n## Table-Driven Tests\n\nThe standard pattern for Go tests. Enables comprehensive coverage with minimal code.\n\n```go\nfunc TestAdd(t *testing.T) {\n    tests := []struct {\n        name     string\n        a, b     int\n        expected int\n    }{\n        {\"positive numbers\", 2, 3, 5},\n        {\"negative numbers\", -1, -2, -3},\n        {\"zero values\", 0, 0, 0},\n        {\"mixed signs\", -1, 1, 0},\n        {\"large numbers\", 1000000, 2000000, 3000000},\n    }\n\n    for _, tt := range tests {\n        t.Run(tt.name, func(t *testing.T) {\n            got := Add(tt.a, tt.b)\n            if got != tt.expected {\n                t.Errorf(\"Add(%d, %d) = %d; want %d\",\n                    tt.a, tt.b, got, tt.expected)\n            }\n        })\n    }\n}\n```\n\n### Table-Driven Tests with Error Cases\n\n```go\nfunc TestParseConfig(t *testing.T) {\n    tests := []struct {\n        name    string\n        input   string\n        want    *Config\n        wantErr bool\n    }{\n        {\n            name:  \"valid config\",\n            input: `{\"host\": \"localhost\", \"port\": 8080}`,\n            want:  &Config{Host: \"localhost\", Port: 8080},\n        },\n        {\n            name:    \"invalid JSON\",\n            input:   `{invalid}`,\n            wantErr: true,\n        },\n        {\n            name:    \"empty input\",\n            input:   \"\",\n            wantErr: true,\n        },\n        {\n            name:  \"minimal config\",\n            input: `{}`,\n            want:  &Config{}, \u002F\u002F Zero value config\n        },\n    }\n\n    for _, tt := range tests {\n        t.Run(tt.name, func(t *testing.T) {\n            got, err := ParseConfig(tt.input)\n\n            if tt.wantErr {\n                if err == nil {\n                    t.Error(\"expected error, got nil\")\n                }\n                return\n            }\n\n            if err != nil {\n                t.Fatalf(\"unexpected error: %v\", err)\n            }\n\n            if !reflect.DeepEqual(got, tt.want) {\n                t.Errorf(\"got %+v; want %+v\", got, tt.want)\n            }\n        })\n    }\n}\n```\n\n## Subtests and Sub-benchmarks\n\n### Organizing Related Tests\n\n```go\nfunc TestUser(t *testing.T) {\n    \u002F\u002F Setup shared by all subtests\n    db := setupTestDB(t)\n\n    t.Run(\"Create\", func(t *testing.T) {\n        user := &User{Name: \"Alice\"}\n        err := db.CreateUser(user)\n        if err != nil {\n            t.Fatalf(\"CreateUser failed: %v\", err)\n        }\n        if user.ID == \"\" {\n            t.Error(\"expected user ID to be set\")\n        }\n    })\n\n    t.Run(\"Get\", func(t *testing.T) {\n        user, err := db.GetUser(\"alice-id\")\n        if err != nil {\n            t.Fatalf(\"GetUser failed: %v\", err)\n        }\n        if user.Name != \"Alice\" {\n            t.Errorf(\"got name %q; want %q\", user.Name, \"Alice\")\n        }\n    })\n\n    t.Run(\"Update\", func(t *testing.T) {\n        \u002F\u002F ...\n    })\n\n    t.Run(\"Delete\", func(t *testing.T) {\n        \u002F\u002F ...\n    })\n}\n```\n\n### Parallel Subtests\n\n```go\nfunc TestParallel(t *testing.T) {\n    tests := []struct {\n        name  string\n        input string\n    }{\n        {\"case1\", \"input1\"},\n        {\"case2\", \"input2\"},\n        {\"case3\", \"input3\"},\n    }\n\n    for _, tt := range tests {\n        tt := tt \u002F\u002F Capture range variable\n        t.Run(tt.name, func(t *testing.T) {\n            t.Parallel() \u002F\u002F Run subtests in parallel\n            result := Process(tt.input)\n            \u002F\u002F assertions...\n            _ = result\n        })\n    }\n}\n```\n\n## Test Helpers\n\n### Helper Functions\n\n```go\nfunc setupTestDB(t *testing.T) *sql.DB {\n    t.Helper() \u002F\u002F Marks this as a helper function\n\n    db, err := sql.Open(\"sqlite3\", \":memory:\")\n    if err != nil {\n        t.Fatalf(\"failed to open database: %v\", err)\n    }\n\n    \u002F\u002F Cleanup when test finishes\n    t.Cleanup(func() {\n        db.Close()\n    })\n\n    \u002F\u002F Run migrations\n    if _, err := db.Exec(schema); err != nil {\n        t.Fatalf(\"failed to create schema: %v\", err)\n    }\n\n    return db\n}\n\nfunc assertNoError(t *testing.T, err error) {\n    t.Helper()\n    if err != nil {\n        t.Fatalf(\"unexpected error: %v\", err)\n    }\n}\n\nfunc assertEqual[T comparable](t *testing.T, got, want T) {\n    t.Helper()\n    if got != want {\n        t.Errorf(\"got %v; want %v\", got, want)\n    }\n}\n```\n\n### Temporary Files and Directories\n\n```go\nfunc TestFileProcessing(t *testing.T) {\n    \u002F\u002F Create temp directory - automatically cleaned up\n    tmpDir := t.TempDir()\n\n    \u002F\u002F Create test file\n    testFile := filepath.Join(tmpDir, \"test.txt\")\n    err := os.WriteFile(testFile, []byte(\"test content\"), 0644)\n    if err != nil {\n        t.Fatalf(\"failed to create test file: %v\", err)\n    }\n\n    \u002F\u002F Run test\n    result, err := ProcessFile(testFile)\n    if err != nil {\n        t.Fatalf(\"ProcessFile failed: %v\", err)\n    }\n\n    \u002F\u002F Assert...\n    _ = result\n}\n```\n\n## Golden Files\n\nTesting against expected output files stored in `testdata\u002F`.\n\n```go\nvar update = flag.Bool(\"update\", false, \"update golden files\")\n\nfunc TestRender(t *testing.T) {\n    tests := []struct {\n        name  string\n        input Template\n    }{\n        {\"simple\", Template{Name: \"test\"}},\n        {\"complex\", Template{Name: \"test\", Items: []string{\"a\", \"b\"}}},\n    }\n\n    for _, tt := range tests {\n        t.Run(tt.name, func(t *testing.T) {\n            got := Render(tt.input)\n\n            golden := filepath.Join(\"testdata\", tt.name+\".golden\")\n\n            if *update {\n                \u002F\u002F Update golden file: go test -update\n                err := os.WriteFile(golden, got, 0644)\n                if err != nil {\n                    t.Fatalf(\"failed to update golden file: %v\", err)\n                }\n            }\n\n            want, err := os.ReadFile(golden)\n            if err != nil {\n                t.Fatalf(\"failed to read golden file: %v\", err)\n            }\n\n            if !bytes.Equal(got, want) {\n                t.Errorf(\"output mismatch:\\ngot:\\n%s\\nwant:\\n%s\", got, want)\n            }\n        })\n    }\n}\n```\n\n## Mocking with Interfaces\n\n### Interface-Based Mocking\n\n```go\n\u002F\u002F Define interface for dependencies\ntype UserRepository interface {\n    GetUser(id string) (*User, error)\n    SaveUser(user *User) error\n}\n\n\u002F\u002F Production implementation\ntype PostgresUserRepository struct {\n    db *sql.DB\n}\n\nfunc (r *PostgresUserRepository) GetUser(id string) (*User, error) {\n    \u002F\u002F Real database query\n}\n\n\u002F\u002F Mock implementation for tests\ntype MockUserRepository struct {\n    GetUserFunc  func(id string) (*User, error)\n    SaveUserFunc func(user *User) error\n}\n\nfunc (m *MockUserRepository) GetUser(id string) (*User, error) {\n    return m.GetUserFunc(id)\n}\n\nfunc (m *MockUserRepository) SaveUser(user *User) error {\n    return m.SaveUserFunc(user)\n}\n\n\u002F\u002F Test using mock\nfunc TestUserService(t *testing.T) {\n    mock := &MockUserRepository{\n        GetUserFunc: func(id string) (*User, error) {\n            if id == \"123\" {\n                return &User{ID: \"123\", Name: \"Alice\"}, nil\n            }\n            return nil, ErrNotFound\n        },\n    }\n\n    service := NewUserService(mock)\n\n    user, err := service.GetUserProfile(\"123\")\n    if err != nil {\n        t.Fatalf(\"unexpected error: %v\", err)\n    }\n    if user.Name != \"Alice\" {\n        t.Errorf(\"got name %q; want %q\", user.Name, \"Alice\")\n    }\n}\n```\n\n## Benchmarks\n\n### Basic Benchmarks\n\n```go\nfunc BenchmarkProcess(b *testing.B) {\n    data := generateTestData(1000)\n    b.ResetTimer() \u002F\u002F Don't count setup time\n\n    for i := 0; i \u003C b.N; i++ {\n        Process(data)\n    }\n}\n\n\u002F\u002F Run: go test -bench=BenchmarkProcess -benchmem\n\u002F\u002F Output: BenchmarkProcess-8   10000   105234 ns\u002Fop   4096 B\u002Fop   10 allocs\u002Fop\n```\n\n### Benchmark with Different Sizes\n\n```go\nfunc BenchmarkSort(b *testing.B) {\n    sizes := []int{100, 1000, 10000, 100000}\n\n    for _, size := range sizes {\n        b.Run(fmt.Sprintf(\"size=%d\", size), func(b *testing.B) {\n            data := generateRandomSlice(size)\n            b.ResetTimer()\n\n            for i := 0; i \u003C b.N; i++ {\n                \u002F\u002F Make a copy to avoid sorting already sorted data\n                tmp := make([]int, len(data))\n                copy(tmp, data)\n                sort.Ints(tmp)\n            }\n        })\n    }\n}\n```\n\n### Memory Allocation Benchmarks\n\n```go\nfunc BenchmarkStringConcat(b *testing.B) {\n    parts := []string{\"hello\", \"world\", \"foo\", \"bar\", \"baz\"}\n\n    b.Run(\"plus\", func(b *testing.B) {\n        for i := 0; i \u003C b.N; i++ {\n            var s string\n            for _, p := range parts {\n                s += p\n            }\n            _ = s\n        }\n    })\n\n    b.Run(\"builder\", func(b *testing.B) {\n        for i := 0; i \u003C b.N; i++ {\n            var sb strings.Builder\n            for _, p := range parts {\n                sb.WriteString(p)\n            }\n            _ = sb.String()\n        }\n    })\n\n    b.Run(\"join\", func(b *testing.B) {\n        for i := 0; i \u003C b.N; i++ {\n            _ = strings.Join(parts, \"\")\n        }\n    })\n}\n```\n\n## Fuzzing (Go 1.18+)\n\n### Basic Fuzz Test\n\n```go\nfunc FuzzParseJSON(f *testing.F) {\n    \u002F\u002F Add seed corpus\n    f.Add(`{\"name\": \"test\"}`)\n    f.Add(`{\"count\": 123}`)\n    f.Add(`[]`)\n    f.Add(`\"\"`)\n\n    f.Fuzz(func(t *testing.T, input string) {\n        var result map[string]interface{}\n        err := json.Unmarshal([]byte(input), &result)\n\n        if err != nil {\n            \u002F\u002F Invalid JSON is expected for random input\n            return\n        }\n\n        \u002F\u002F If parsing succeeded, re-encoding should work\n        _, err = json.Marshal(result)\n        if err != nil {\n            t.Errorf(\"Marshal failed after successful Unmarshal: %v\", err)\n        }\n    })\n}\n\n\u002F\u002F Run: go test -fuzz=FuzzParseJSON -fuzztime=30s\n```\n\n### Fuzz Test with Multiple Inputs\n\n```go\nfunc FuzzCompare(f *testing.F) {\n    f.Add(\"hello\", \"world\")\n    f.Add(\"\", \"\")\n    f.Add(\"abc\", \"abc\")\n\n    f.Fuzz(func(t *testing.T, a, b string) {\n        result := Compare(a, b)\n\n        \u002F\u002F Property: Compare(a, a) should always equal 0\n        if a == b && result != 0 {\n            t.Errorf(\"Compare(%q, %q) = %d; want 0\", a, b, result)\n        }\n\n        \u002F\u002F Property: Compare(a, b) and Compare(b, a) should have opposite signs\n        reverse := Compare(b, a)\n        if (result > 0 && reverse >= 0) || (result \u003C 0 && reverse \u003C= 0) {\n            if result != 0 || reverse != 0 {\n                t.Errorf(\"Compare(%q, %q) = %d, Compare(%q, %q) = %d; inconsistent\",\n                    a, b, result, b, a, reverse)\n            }\n        }\n    })\n}\n```\n\n## Test Coverage\n\n### Running Coverage\n\n```bash\n# Basic coverage\ngo test -cover .\u002F...\n\n# Generate coverage profile\ngo test -coverprofile=coverage.out .\u002F...\n\n# View coverage in browser\ngo tool cover -html=coverage.out\n\n# View coverage by function\ngo tool cover -func=coverage.out\n\n# Coverage with race detection\ngo test -race -coverprofile=coverage.out .\u002F...\n```\n\n### Coverage Targets\n\n| Code Type | Target |\n|-----------|--------|\n| Critical business logic | 100% |\n| Public APIs | 90%+ |\n| General code | 80%+ |\n| Generated code | Exclude |\n\n### Excluding Generated Code from Coverage\n\n```go\n\u002F\u002Fgo:generate mockgen -source=interface.go -destination=mock_interface.go\n\n\u002F\u002F In coverage profile, exclude with build tags:\n\u002F\u002F go test -cover -tags=!generate .\u002F...\n```\n\n## HTTP Handler Testing\n\n```go\nfunc TestHealthHandler(t *testing.T) {\n    \u002F\u002F Create request\n    req := httptest.NewRequest(http.MethodGet, \"\u002Fhealth\", nil)\n    w := httptest.NewRecorder()\n\n    \u002F\u002F Call handler\n    HealthHandler(w, req)\n\n    \u002F\u002F Check response\n    resp := w.Result()\n    defer resp.Body.Close()\n\n    if resp.StatusCode != http.StatusOK {\n        t.Errorf(\"got status %d; want %d\", resp.StatusCode, http.StatusOK)\n    }\n\n    body, _ := io.ReadAll(resp.Body)\n    if string(body) != \"OK\" {\n        t.Errorf(\"got body %q; want %q\", body, \"OK\")\n    }\n}\n\nfunc TestAPIHandler(t *testing.T) {\n    tests := []struct {\n        name       string\n        method     string\n        path       string\n        body       string\n        wantStatus int\n        wantBody   string\n    }{\n        {\n            name:       \"get user\",\n            method:     http.MethodGet,\n            path:       \"\u002Fusers\u002F123\",\n            wantStatus: http.StatusOK,\n            wantBody:   `{\"id\":\"123\",\"name\":\"Alice\"}`,\n        },\n        {\n            name:       \"not found\",\n            method:     http.MethodGet,\n            path:       \"\u002Fusers\u002F999\",\n            wantStatus: http.StatusNotFound,\n        },\n        {\n            name:       \"create user\",\n            method:     http.MethodPost,\n            path:       \"\u002Fusers\",\n            body:       `{\"name\":\"Bob\"}`,\n            wantStatus: http.StatusCreated,\n        },\n    }\n\n    handler := NewAPIHandler()\n\n    for _, tt := range tests {\n        t.Run(tt.name, func(t *testing.T) {\n            var body io.Reader\n            if tt.body != \"\" {\n                body = strings.NewReader(tt.body)\n            }\n\n            req := httptest.NewRequest(tt.method, tt.path, body)\n            req.Header.Set(\"Content-Type\", \"application\u002Fjson\")\n            w := httptest.NewRecorder()\n\n            handler.ServeHTTP(w, req)\n\n            if w.Code != tt.wantStatus {\n                t.Errorf(\"got status %d; want %d\", w.Code, tt.wantStatus)\n            }\n\n            if tt.wantBody != \"\" && w.Body.String() != tt.wantBody {\n                t.Errorf(\"got body %q; want %q\", w.Body.String(), tt.wantBody)\n            }\n        })\n    }\n}\n```\n\n## Testing Commands\n\n```bash\n# Run all tests\ngo test .\u002F...\n\n# Run tests with verbose output\ngo test -v .\u002F...\n\n# Run specific test\ngo test -run TestAdd .\u002F...\n\n# Run tests matching pattern\ngo test -run \"TestUser\u002FCreate\" .\u002F...\n\n# Run tests with race detector\ngo test -race .\u002F...\n\n# Run tests with coverage\ngo test -cover -coverprofile=coverage.out .\u002F...\n\n# Run short tests only\ngo test -short .\u002F...\n\n# Run tests with timeout\ngo test -timeout 30s .\u002F...\n\n# Run benchmarks\ngo test -bench=. -benchmem .\u002F...\n\n# Run fuzzing\ngo test -fuzz=FuzzParse -fuzztime=30s .\u002F...\n\n# Count test runs (for flaky test detection)\ngo test -count=10 .\u002F...\n```\n\n## Best Practices\n\n**DO:**\n- Write tests FIRST (TDD)\n- Use table-driven tests for comprehensive coverage\n- Test behavior, not implementation\n- Use `t.Helper()` in helper functions\n- Use `t.Parallel()` for independent tests\n- Clean up resources with `t.Cleanup()`\n- Use meaningful test names that describe the scenario\n\n**DON'T:**\n- Test private functions directly (test through public API)\n- Use `time.Sleep()` in tests (use channels or conditions)\n- Ignore flaky tests (fix or remove them)\n- Mock everything (prefer integration tests when possible)\n- Skip error path testing\n\n## Integration with CI\u002FCD\n\n```yaml\n# GitHub Actions example\ntest:\n  runs-on: ubuntu-latest\n  steps:\n    - uses: actions\u002Fcheckout@v4\n    - uses: actions\u002Fsetup-go@v5\n      with:\n        go-version: '1.22'\n\n    - name: Run tests\n      run: go test -race -coverprofile=coverage.out .\u002F...\n\n    - name: Check coverage\n      run: |\n        go tool cover -func=coverage.out | grep total | awk '{print $3}' | \\\n        awk -F'%' '{if ($1 \u003C 80) exit 1}'\n```\n\n**Remember**: Tests are documentation. They show how your code is meant to be used. Write them clearly and keep them up to date.\n","# Go Testing Patterns\n\nComprehensive Go testing patterns for writing reliable, maintainable tests following TDD methodology.\n\n## When to Activate\n\n- Writing new Go functions or methods\n- Adding test coverage to existing code\n- Creating benchmarks for performance-critical code\n- Implementing fuzz tests for input validation\n- Following TDD workflow in Go projects\n\n## TDD Workflow for Go\n\n### The RED-GREEN-REFACTOR Cycle\n\n```\nRED     → Write a failing test first\nGREEN   → Write minimal code to pass the test\nREFACTOR → Improve code while keeping tests green\nREPEAT  → Continue with next requirement\n```\n\n### Step-by-Step TDD in Go\n\n```go\n\u002F\u002F Step 1: Define the interface\u002Fsignature\n\u002F\u002F calculator.go\npackage calculator\n\nfunc Add(a, b int) int {\n    panic(\"not implemented\") \u002F\u002F Placeholder\n}\n\n\u002F\u002F Step 2: Write failing test (RED)\n\u002F\u002F calculator_test.go\npackage calculator\n\nimport \"testing\"\n\nfunc TestAdd(t *testing.T) {\n    got := Add(2, 3)\n    want := 5\n    if got != want {\n        t.Errorf(\"Add(2, 3) = %d; want %d\", got, want)\n    }\n}\n\n\u002F\u002F Step 3: Run test - verify FAIL\n\u002F\u002F $ go test\n\u002F\u002F --- FAIL: TestAdd (0.00s)\n\u002F\u002F panic: not implemented\n\n\u002F\u002F Step 4: Implement minimal code (GREEN)\nfunc Add(a, b int) int {\n    return a + b\n}\n\n\u002F\u002F Step 5: Run test - verify PASS\n\u002F\u002F $ go test\n\u002F\u002F PASS\n\n\u002F\u002F Step 6: Refactor if needed, verify tests still pass\n```\n\n## Table-Driven Tests\n\nThe standard pattern for Go tests. Enables comprehensive coverage with minimal code.\n\n```go\nfunc TestAdd(t *testing.T) {\n    tests := []struct {\n        name     string\n        a, b     int\n        expected int\n    }{\n        {\"positive numbers\", 2, 3, 5},\n        {\"negative numbers\", -1, -2, -3},\n        {\"zero values\", 0, 0, 0},\n        {\"mixed signs\", -1, 1, 0},\n        {\"large numbers\", 1000000, 2000000, 3000000},\n    }\n\n    for _, tt := range tests {\n        t.Run(tt.name, func(t *testing.T) {\n            got := Add(tt.a, tt.b)\n            if got != tt.expected {\n                t.Errorf(\"Add(%d, %d) = %d; want %d\",\n                    tt.a, tt.b, got, tt.expected)\n            }\n        })\n    }\n}\n```\n\n### Table-Driven Tests with Error Cases\n\n```go\nfunc TestParseConfig(t *testing.T) {\n    tests := []struct {\n        name    string\n        input   string\n        want    *Config\n        wantErr bool\n    }{\n        {\n            name:  \"valid config\",\n            input: `{\"host\": \"localhost\", \"port\": 8080}`,\n            want:  &Config{Host: \"localhost\", Port: 8080},\n        },\n        {\n            name:    \"invalid JSON\",\n            input:   `{invalid}`,\n            wantErr: true,\n        },\n        {\n            name:    \"empty input\",\n            input:   \"\",\n            wantErr: true,\n        },\n        {\n            name:  \"minimal config\",\n            input: `{}`,\n            want:  &Config{}, \u002F\u002F Zero value config\n        },\n    }\n\n    for _, tt := range tests {\n        t.Run(tt.name, func(t *testing.T) {\n            got, err := ParseConfig(tt.input)\n\n            if tt.wantErr {\n                if err == nil {\n                    t.Error(\"expected error, got nil\")\n                }\n                return\n            }\n\n            if err != nil {\n                t.Fatalf(\"unexpected error: %v\", err)\n            }\n\n            if !reflect.DeepEqual(got, tt.want) {\n                t.Errorf(\"got %+v; want %+v\", got, tt.want)\n            }\n        })\n    }\n}\n```\n\n## Subtests and Sub-benchmarks\n\n### Organizing Related Tests\n\n```go\nfunc TestUser(t *testing.T) {\n    \u002F\u002F Setup shared by all subtests\n    db := setupTestDB(t)\n\n    t.Run(\"Create\", func(t *testing.T) {\n        user := &User{Name: \"Alice\"}\n        err := db.CreateUser(user)\n        if err != nil {\n            t.Fatalf(\"CreateUser failed: %v\", err)\n        }\n        if user.ID == \"\" {\n            t.Error(\"expected user ID to be set\")\n        }\n    })\n\n    t.Run(\"Get\", func(t *testing.T) {\n        user, err := db.GetUser(\"alice-id\")\n        if err != nil {\n            t.Fatalf(\"GetUser failed: %v\", err)\n        }\n        if user.Name != \"Alice\" {\n            t.Errorf(\"got name %q; want %q\", user.Name, \"Alice\")\n        }\n    })\n\n    t.Run(\"Update\", func(t *testing.T) {\n        \u002F\u002F ...\n    })\n\n    t.Run(\"Delete\", func(t *testing.T) {\n        \u002F\u002F ...\n    })\n}\n```\n\n### Parallel Subtests\n\n```go\nfunc TestParallel(t *testing.T) {\n    tests := []struct {\n        name  string\n        input string\n    }{\n        {\"case1\", \"input1\"},\n        {\"case2\", \"input2\"},\n        {\"case3\", \"input3\"},\n    }\n\n    for _, tt := range tests {\n        tt := tt \u002F\u002F Capture range variable\n        t.Run(tt.name, func(t *testing.T) {\n            t.Parallel() \u002F\u002F Run subtests in parallel\n            result := Process(tt.input)\n            \u002F\u002F assertions...\n            _ = result\n        })\n    }\n}\n```\n\n## Test Helpers\n\n### Helper Functions\n\n```go\nfunc setupTestDB(t *testing.T) *sql.DB {\n    t.Helper() \u002F\u002F Marks this as a helper function\n\n    db, err := sql.Open(\"sqlite3\", \":memory:\")\n    if err != nil {\n        t.Fatalf(\"failed to open database: %v\", err)\n    }\n\n    \u002F\u002F Cleanup when test finishes\n    t.Cleanup(func() {\n        db.Close()\n    })\n\n    \u002F\u002F Run migrations\n    if _, err := db.Exec(schema); err != nil {\n        t.Fatalf(\"failed to create schema: %v\", err)\n    }\n\n    return db\n}\n\nfunc assertNoError(t *testing.T, err error) {\n    t.Helper()\n    if err != nil {\n        t.Fatalf(\"unexpected error: %v\", err)\n    }\n}\n\nfunc assertEqual[T comparable](t *testing.T, got, want T) {\n    t.Helper()\n    if got != want {\n        t.Errorf(\"got %v; want %v\", got, want)\n    }\n}\n```\n\n### Temporary Files and Directories\n\n```go\nfunc TestFileProcessing(t *testing.T) {\n    \u002F\u002F Create temp directory - automatically cleaned up\n    tmpDir := t.TempDir()\n\n    \u002F\u002F Create test file\n    testFile := filepath.Join(tmpDir, \"test.txt\")\n    err := os.WriteFile(testFile, []byte(\"test content\"), 0644)\n    if err != nil {\n        t.Fatalf(\"failed to create test file: %v\", err)\n    }\n\n    \u002F\u002F Run test\n    result, err := ProcessFile(testFile)\n    if err != nil {\n        t.Fatalf(\"ProcessFile failed: %v\", err)\n    }\n\n    \u002F\u002F Assert...\n    _ = result\n}\n```\n\n## Golden Files\n\nTesting against expected output files stored in `testdata\u002F`.\n\n```go\nvar update = flag.Bool(\"update\", false, \"update golden files\")\n\nfunc TestRender(t *testing.T) {\n    tests := []struct {\n        name  string\n        input Template\n    }{\n        {\"simple\", Template{Name: \"test\"}},\n        {\"complex\", Template{Name: \"test\", Items: []string{\"a\", \"b\"}}},\n    }\n\n    for _, tt := range tests {\n        t.Run(tt.name, func(t *testing.T) {\n            got := Render(tt.input)\n\n            golden := filepath.Join(\"testdata\", tt.name+\".golden\")\n\n            if *update {\n                \u002F\u002F Update golden file: go test -update\n                err := os.WriteFile(golden, got, 0644)\n                if err != nil {\n                    t.Fatalf(\"failed to update golden file: %v\", err)\n                }\n            }\n\n            want, err := os.ReadFile(golden)\n            if err != nil {\n                t.Fatalf(\"failed to read golden file: %v\", err)\n            }\n\n            if !bytes.Equal(got, want) {\n                t.Errorf(\"output mismatch:\\ngot:\\n%s\\nwant:\\n%s\", got, want)\n            }\n        })\n    }\n}\n```\n\n## Mocking with Interfaces\n\n### Interface-Based Mocking\n\n```go\n\u002F\u002F Define interface for dependencies\ntype UserRepository interface {\n    GetUser(id string) (*User, error)\n    SaveUser(user *User) error\n}\n\n\u002F\u002F Production implementation\ntype PostgresUserRepository struct {\n    db *sql.DB\n}\n\nfunc (r *PostgresUserRepository) GetUser(id string) (*User, error) {\n    \u002F\u002F Real database query\n}\n\n\u002F\u002F Mock implementation for tests\ntype MockUserRepository struct {\n    GetUserFunc  func(id string) (*User, error)\n    SaveUserFunc func(user *User) error\n}\n\nfunc (m *MockUserRepository) GetUser(id string) (*User, error) {\n    return m.GetUserFunc(id)\n}\n\nfunc (m *MockUserRepository) SaveUser(user *User) error {\n    return m.SaveUserFunc(user)\n}\n\n\u002F\u002F Test using mock\nfunc TestUserService(t *testing.T) {\n    mock := &MockUserRepository{\n        GetUserFunc: func(id string) (*User, error) {\n            if id == \"123\" {\n                return &User{ID: \"123\", Name: \"Alice\"}, nil\n            }\n            return nil, ErrNotFound\n        },\n    }\n\n    service := NewUserService(mock)\n\n    user, err := service.GetUserProfile(\"123\")\n    if err != nil {\n        t.Fatalf(\"unexpected error: %v\", err)\n    }\n    if user.Name != \"Alice\" {\n        t.Errorf(\"got name %q; want %q\", user.Name, \"Alice\")\n    }\n}\n```\n\n## Benchmarks\n\n### Basic Benchmarks\n\n```go\nfunc BenchmarkProcess(b *testing.B) {\n    data := generateTestData(1000)\n    b.ResetTimer() \u002F\u002F Don't count setup time\n\n    for i := 0; i \u003C b.N; i++ {\n        Process(data)\n    }\n}\n\n\u002F\u002F Run: go test -bench=BenchmarkProcess -benchmem\n\u002F\u002F Output: BenchmarkProcess-8   10000   105234 ns\u002Fop   4096 B\u002Fop   10 allocs\u002Fop\n```\n\n### Benchmark with Different Sizes\n\n```go\nfunc BenchmarkSort(b *testing.B) {\n    sizes := []int{100, 1000, 10000, 100000}\n\n    for _, size := range sizes {\n        b.Run(fmt.Sprintf(\"size=%d\", size), func(b *testing.B) {\n            data := generateRandomSlice(size)\n            b.ResetTimer()\n\n            for i := 0; i \u003C b.N; i++ {\n                \u002F\u002F Make a copy to avoid sorting already sorted data\n                tmp := make([]int, len(data))\n                copy(tmp, data)\n                sort.Ints(tmp)\n            }\n        })\n    }\n}\n```\n\n### Memory Allocation Benchmarks\n\n```go\nfunc BenchmarkStringConcat(b *testing.B) {\n    parts := []string{\"hello\", \"world\", \"foo\", \"bar\", \"baz\"}\n\n    b.Run(\"plus\", func(b *testing.B) {\n        for i := 0; i \u003C b.N; i++ {\n            var s string\n            for _, p := range parts {\n                s += p\n            }\n            _ = s\n        }\n    })\n\n    b.Run(\"builder\", func(b *testing.B) {\n        for i := 0; i \u003C b.N; i++ {\n            var sb strings.Builder\n            for _, p := range parts {\n                sb.WriteString(p)\n            }\n            _ = sb.String()\n        }\n    })\n\n    b.Run(\"join\", func(b *testing.B) {\n        for i := 0; i \u003C b.N; i++ {\n            _ = strings.Join(parts, \"\")\n        }\n    })\n}\n```\n\n## Fuzzing (Go 1.18+)\n\n### Basic Fuzz Test\n\n```go\nfunc FuzzParseJSON(f *testing.F) {\n    \u002F\u002F Add seed corpus\n    f.Add(`{\"name\": \"test\"}`)\n    f.Add(`{\"count\": 123}`)\n    f.Add(`[]`)\n    f.Add(`\"\"`)\n\n    f.Fuzz(func(t *testing.T, input string) {\n        var result map[string]interface{}\n        err := json.Unmarshal([]byte(input), &result)\n\n        if err != nil {\n            \u002F\u002F Invalid JSON is expected for random input\n            return\n        }\n\n        \u002F\u002F If parsing succeeded, re-encoding should work\n        _, err = json.Marshal(result)\n        if err != nil {\n            t.Errorf(\"Marshal failed after successful Unmarshal: %v\", err)\n        }\n    })\n}\n\n\u002F\u002F Run: go test -fuzz=FuzzParseJSON -fuzztime=30s\n```\n\n### Fuzz Test with Multiple Inputs\n\n```go\nfunc FuzzCompare(f *testing.F) {\n    f.Add(\"hello\", \"world\")\n    f.Add(\"\", \"\")\n    f.Add(\"abc\", \"abc\")\n\n    f.Fuzz(func(t *testing.T, a, b string) {\n        result := Compare(a, b)\n\n        \u002F\u002F Property: Compare(a, a) should always equal 0\n        if a == b && result != 0 {\n            t.Errorf(\"Compare(%q, %q) = %d; want 0\", a, b, result)\n        }\n\n        \u002F\u002F Property: Compare(a, b) and Compare(b, a) should have opposite signs\n        reverse := Compare(b, a)\n        if (result > 0 && reverse >= 0) || (result \u003C 0 && reverse \u003C= 0) {\n            if result != 0 || reverse != 0 {\n                t.Errorf(\"Compare(%q, %q) = %d, Compare(%q, %q) = %d; inconsistent\",\n                    a, b, result, b, a, reverse)\n            }\n        }\n    })\n}\n```\n\n## Test Coverage\n\n### Running Coverage\n\n```bash\n# Basic coverage\ngo test -cover .\u002F...\n\n# Generate coverage profile\ngo test -coverprofile=coverage.out .\u002F...\n\n# View coverage in browser\ngo tool cover -html=coverage.out\n\n# View coverage by function\ngo tool cover -func=coverage.out\n\n# Coverage with race detection\ngo test -race -coverprofile=coverage.out .\u002F...\n```\n\n### Coverage Targets\n\n| Code Type | Target |\n|-----------|--------|\n| Critical business logic | 100% |\n| Public APIs | 90%+ |\n| General code | 80%+ |\n| Generated code | Exclude |\n\n### Excluding Generated Code from Coverage\n\n```go\n\u002F\u002Fgo:generate mockgen -source=interface.go -destination=mock_interface.go\n\n\u002F\u002F In coverage profile, exclude with build tags:\n\u002F\u002F go test -cover -tags=!generate .\u002F...\n```\n\n## HTTP Handler Testing\n\n```go\nfunc TestHealthHandler(t *testing.T) {\n    \u002F\u002F Create request\n    req := httptest.NewRequest(http.MethodGet, \"\u002Fhealth\", nil)\n    w := httptest.NewRecorder()\n\n    \u002F\u002F Call handler\n    HealthHandler(w, req)\n\n    \u002F\u002F Check response\n    resp := w.Result()\n    defer resp.Body.Close()\n\n    if resp.StatusCode != http.StatusOK {\n        t.Errorf(\"got status %d; want %d\", resp.StatusCode, http.StatusOK)\n    }\n\n    body, _ := io.ReadAll(resp.Body)\n    if string(body) != \"OK\" {\n        t.Errorf(\"got body %q; want %q\", body, \"OK\")\n    }\n}\n\nfunc TestAPIHandler(t *testing.T) {\n    tests := []struct {\n        name       string\n        method     string\n        path       string\n        body       string\n        wantStatus int\n        wantBody   string\n    }{\n        {\n            name:       \"get user\",\n            method:     http.MethodGet,\n            path:       \"\u002Fusers\u002F123\",\n            wantStatus: http.StatusOK,\n            wantBody:   `{\"id\":\"123\",\"name\":\"Alice\"}`,\n        },\n        {\n            name:       \"not found\",\n            method:     http.MethodGet,\n            path:       \"\u002Fusers\u002F999\",\n            wantStatus: http.StatusNotFound,\n        },\n        {\n            name:       \"create user\",\n            method:     http.MethodPost,\n            path:       \"\u002Fusers\",\n            body:       `{\"name\":\"Bob\"}`,\n            wantStatus: http.StatusCreated,\n        },\n    }\n\n    handler := NewAPIHandler()\n\n    for _, tt := range tests {\n        t.Run(tt.name, func(t *testing.T) {\n            var body io.Reader\n            if tt.body != \"\" {\n                body = strings.NewReader(tt.body)\n            }\n\n            req := httptest.NewRequest(tt.method, tt.path, body)\n            req.Header.Set(\"Content-Type\", \"application\u002Fjson\")\n            w := httptest.NewRecorder()\n\n            handler.ServeHTTP(w, req)\n\n            if w.Code != tt.wantStatus {\n                t.Errorf(\"got status %d; want %d\", w.Code, tt.wantStatus)\n            }\n\n            if tt.wantBody != \"\" && w.Body.String() != tt.wantBody {\n                t.Errorf(\"got body %q; want %q\", w.Body.String(), tt.wantBody)\n            }\n        })\n    }\n}\n```\n\n## Testing Commands\n\n```bash\n# Run all tests\ngo test .\u002F...\n\n# Run tests with verbose output\ngo test -v .\u002F...\n\n# Run specific test\ngo test -run TestAdd .\u002F...\n\n# Run tests matching pattern\ngo test -run \"TestUser\u002FCreate\" .\u002F...\n\n# Run tests with race detector\ngo test -race .\u002F...\n\n# Run tests with coverage\ngo test -cover -coverprofile=coverage.out .\u002F...\n\n# Run short tests only\ngo test -short .\u002F...\n\n# Run tests with timeout\ngo test -timeout 30s .\u002F...\n\n# Run benchmarks\ngo test -bench=. -benchmem .\u002F...\n\n# Run fuzzing\ngo test -fuzz=FuzzParse -fuzztime=30s .\u002F...\n\n# Count test runs (for flaky test detection)\ngo test -count=10 .\u002F...\n```\n\n## Best Practices\n\n**DO:**\n- Write tests FIRST (TDD)\n- Use table-driven tests for comprehensive coverage\n- Test behavior, not implementation\n- Use `t.Helper()` in helper functions\n- Use `t.Parallel()` for independent tests\n- Clean up resources with `t.Cleanup()`\n- Use meaningful test names that describe the scenario\n\n**DON'T:**\n- Test private functions directly (test through public API)\n- Use `time.Sleep()` in tests (use channels or conditions)\n- Ignore flaky tests (fix or remove them)\n- Mock everything (prefer integration tests when possible)\n- Skip error path testing\n\n## Integration with CI\u002FCD\n\n```yaml\n# GitHub Actions example\ntest:\n  runs-on: ubuntu-latest\n  steps:\n    - uses: actions\u002Fcheckout@v4\n    - uses: actions\u002Fsetup-go@v5\n      with:\n        go-version: '1.22'\n\n    - name: Run tests\n      run: go test -race -coverprofile=coverage.out .\u002F...\n\n    - name: Check coverage\n      run: |\n        go tool cover -func=coverage.out | grep total | awk '{print $3}' | \\\n        awk -F'%' '{if ($1 \u003C 80) exit 1}'\n```\n\n**Remember**: Tests are documentation. They show how your code is meant to be used. Write them clearly and keep them up to date.\n",{"name":5,"origin":48,"description":7},"ECC","main","0446e11613ad1942de249b12f7deea3889c25af4","skills\u002Fgolang-testing",0,"https:\u002F\u002Fgithub.com\u002FViewWay\u002Fhermes-by-everythings","https:\u002F\u002Fgithub.com\u002FViewWay","rust can do everything","2026-06-19 23:27:05",{"source":8,"skillName":5,"commands":58,"prompt":68,"zipAvailable":69},[59,62,65],{"tool":60,"command":61},"npx","npx skills add ViewWay\u002Fhermes-by-everythings --skill golang-testing",{"tool":63,"command":64},"bunx","bunx skills add ViewWay\u002Fhermes-by-everythings --skill golang-testing",{"tool":66,"command":67},"pnpm","pnpm dlx skills add ViewWay\u002Fhermes-by-everythings --skill golang-testing","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FViewWay\u002Fhermes-by-everythings\u002Fblob\u002Fmain\u002Fskills\u002Fgolang-testing\u002FSKILL.md",true,[],[72,110,134,159,190,205],{"skillNo":73,"name":74,"nameZh":6,"description":75,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":76,"categories":77,"keywords":89,"publishedAt":43},"01M71EREGWXCCGBGDZ969RZQA7","ui-ux-pro-max","UI\u002FUX design intelligence and implementation guidance for building polished interfaces. Use when the user asks for UI design, UX flows, information architecture, visual style direction, design systems\u002Ftokens, component specs, copy\u002Fmicrocopy, accessibility, or to generate\u002Fcritique\u002Frefine frontend UI (HTML\u002FCSS\u002FJS, React, Next.js, Vue, Svelte, Tailwind). Includes workflows for (1) generating new UI layouts and styling, (2) improving existing UI\u002FUX, (3) producing design-system tokens and component guidelines, and (4) turning UX recommendations into concrete code changes.","https:\u002F\u002Fgithub.com\u002FViewWay\u002Fhermes-by-everythings\u002Fblob\u002Fmain\u002Fskills\u002Fui-ux-pro-max\u002FSKILL.md",[78,81,84],{"categoryNo":79,"categoryName":80,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000009","前端开发",{"categoryNo":82,"categoryName":83,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000015","视觉设计",{"categoryNo":85,"categoryName":86,"taxonomyType":87,"taxonomyTypeDesc":88},"01JBSEEDCAT000000000000032","设计师","PROFESSION","适用职业",[90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109],"ux","max","ui ux","ui","ui ux pro max","pro","information architecture","css","microcopy","direction","Tailwind","flows","frontend","design","new","svelte","design systems","information","workflows","when",{"skillNo":111,"name":112,"nameZh":6,"description":113,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":114,"categories":115,"keywords":116,"publishedAt":43},"01M71ERBY797MAY4HTFMSHPXMY","springboot-verification","Verification loop for Spring Boot projects: build, static analysis, tests with coverage, security scans, and diff review before release or PR.","https:\u002F\u002Fgithub.com\u002FViewWay\u002Fhermes-by-everythings\u002Fblob\u002Fmain\u002Fskills\u002Fspringboot-verification\u002FSKILL.md",[],[117,118,42,119,120,121,122,123,124,33,125,126,127,128,129,130,131,30,132,133],"springboot verification","verification","projects","verification loop","pr","diff","for","static","spring boot","diff review","spring","loop","boot","analysis","review","build","release",{"skillNo":135,"name":136,"nameZh":6,"description":137,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":138,"categories":139,"keywords":143,"publishedAt":43},"01M71ER9TQGK9Y00JEEM6RW9RY","springboot-patterns","Spring Boot architecture patterns, REST API design, layered services, data access, caching, async processing, and logging. Use for Java Spring Boot backend work.","https:\u002F\u002Fgithub.com\u002FViewWay\u002Fhermes-by-everythings\u002Fblob\u002Fmain\u002Fskills\u002Fspringboot-patterns\u002FSKILL.md",[140],{"categoryNo":141,"categoryName":142,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000010","后端与接口",[37,144,145,146,125,103,147,148,149,150,151,152,153,154,155,123,156,157,158,127],"springboot patterns","processing","rest api design","access","caching","architecture","api","spring boot architecture","work","data","architecture patterns","logging","async","java spring","use",{"skillNo":160,"name":161,"nameZh":6,"description":162,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":163,"categories":164,"keywords":172,"publishedAt":43},"01M71ER6XTWDJ0NVE5RFY28RE7","security-auditor","Use when reviewing code for security vulnerabilities, implementing authentication flows, auditing OWASP Top 10, configuring CORS\u002FCSP headers, handling secrets, input validation, SQL injection prevention, XSS protection, or any security-related code review.","https:\u002F\u002Fgithub.com\u002FViewWay\u002Fhermes-by-everythings\u002Fblob\u002Fmain\u002Fskills\u002Fsecurity-auditor\u002FSKILL.md",[165,168,169],{"categoryNo":166,"categoryName":167,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000007","代码审查",{"categoryNo":141,"categoryName":142,"taxonomyType":20,"taxonomyTypeDesc":21},{"categoryNo":170,"categoryName":171,"taxonomyType":87,"taxonomyTypeDesc":88},"01JBSEEDCAT000000000000033","数据分析师",[173,174,175,176,177,101,178,179,180,109,181,182,183,184,131,185,186,187,188,189],"security","security auditor","auditor","authentication","code review","implementing","csrf","Input Validation","encryption","code","vulnerability","xss","top","owasp top 10","audit","sql","secrets",{"skillNo":191,"name":192,"nameZh":6,"description":193,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":194,"categories":195,"keywords":197,"publishedAt":43},"01M71ER4PHRJ1EKXQTQPEPYQ6J","rust-testing","Rust testing patterns including unit tests, integration tests, async testing, property-based testing, mocking, and coverage. Follows TDD methodology.","https:\u002F\u002Fgithub.com\u002FViewWay\u002Fhermes-by-everythings\u002Fblob\u002Fmain\u002Fskills\u002Frust-testing\u002FSKILL.md",[196],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},[198,23,199,42,200,41,37,201,156,202,33,203,28,204,27],"rust","rust testing","unit","integration tests","mocking","unit tests","integration",{"skillNo":206,"name":207,"nameZh":6,"description":208,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":209,"categories":210,"keywords":211,"publishedAt":43},"01M71ER0XW3N4K7YTQSXXWW3M3","rust-patterns","Idiomatic Rust patterns, ownership, error handling, traits, concurrency, and best practices for building safe, performant applications.","https:\u002F\u002Fgithub.com\u002FViewWay\u002Fhermes-by-everythings\u002Fblob\u002Fmain\u002Fskills\u002Frust-patterns\u002FSKILL.md",[],[198,37,212,213,214,215,216,34,123,217,218,219,220],"rust patterns","error","traits","concurrency","safe","applications","best practices","error handling","ownership"]