Skip to content

[testify-expert] Improve Test Quality: pkg/constants/constants_test.go #17515

Description

@github-actions

The test file ./pkg/constants/constants_test.go has been selected for quality improvement by the Testify Uber Super Expert. This issue provides specific, actionable recommendations to enhance test quality and maintainability using testify best practices.

Current State

Metric Value
Test File ./pkg/constants/constants_test.go
Source File ./pkg/constants/constants.go
Test Functions 18 test functions
Lines of Code 738 lines
Manual Assertions 153 (if x != y { t.Errorf(...) } patterns)
Testify Assertions 0 — no assert.* or require.* used

Test Quality Analysis

Strengths ✅

  • Table-driven tests exist: TestConstantValues, TestHelperMethods, TestFeatureFlagConstants, TestModelNameConstants, and others already use tests := []struct{...} patterns with t.Run() — solid foundation.
  • Good edge case coverage: TestGetIntFromEnv_EdgeCases covers whitespace, leading zeros, floats, hex, scientific notation, and negative ranges.
  • Build tag present: //go:build !integration is correctly placed at the top of the file.

Areas for Improvement 🎯

1. Zero testify usage — 153 manual assertions to convert

The entire file uses native t.Errorf / t.Error / t.Fatal patterns. Every single assertion can be simplified with testify, giving clearer failure output and reducing boilerplate.

Current pattern (anti-pattern):

result := GetWorkflowDir()
if result != expected {
    t.Errorf("GetWorkflowDir() = %q, want %q", result, expected)
}

Recommended (testify):

result := GetWorkflowDir()
assert.Equal(t, expected, result, "GetWorkflowDir() should return correct path")

Current pattern (anti-pattern):

if len(DefaultAllowedDomains) == 0 {
    t.Error("DefaultAllowedDomains should not be empty")
}
if len(DefaultAllowedDomains) != len(expectedDomains) {
    t.Errorf("DefaultAllowedDomains length = %d, want %d", ...)
}

Recommended (testify):

assert.NotEmpty(t, DefaultAllowedDomains, "DefaultAllowedDomains should not be empty")
assert.Len(t, DefaultAllowedDomains, len(expectedDomains), "DefaultAllowedDomains should have expected length")

Current pattern in TestGetIntFromEnv (anti-pattern):

if result != tt.expected {
    t.Errorf("Expected %d, got %d", tt.expected, result)
}

Recommended:

assert.Equal(t, tt.expected, result, "GetIntFromEnv(%q) should return %d", tt.envValue, tt.expected)
2. Missing test for GetEngineOption function

GetEngineOption is an exported function in constants.go with no corresponding test. It looks up an EngineOption by engine value string and returns nil if not found — a clear candidate for table-driven testing.

// pkg/constants/constants.go
func GetEngineOption(engineValue string) *EngineOption {
    for i := range EngineOptions {
        if EngineOptions[i].Value == engineValue {
            return &EngineOptions[i]
        }
    }
    return nil  // nil return path untested!
}

Recommended new test:

func TestGetEngineOption(t *testing.T) {
    tests := []struct {
        name        string
        engineValue string
        wantNil     bool
        wantValue   string
    }{
        {
            name:        "valid copilot engine",
            engineValue: "copilot",
            wantNil:     false,
            wantValue:   "copilot",
        },
        {
            name:        "valid claude engine",
            engineValue: "claude",
            wantNil:     false,
            wantValue:   "claude",
        },
        {
            name:        "valid codex engine",
            engineValue: "codex",
            wantNil:     false,
            wantValue:   "codex",
        },
        {
            name:        "unknown engine returns nil",
            engineValue: "unknown-engine",
            wantNil:     true,
        },
        {
            name:        "empty string returns nil",
            engineValue: "",
            wantNil:     true,
        },
        {
            name:        "case sensitive - uppercase returns nil",
            engineValue: "COPILOT",
            wantNil:     true,
        },
    }

    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            result := GetEngineOption(tt.engineValue)

            if tt.wantNil {
                assert.Nil(t, result, "GetEngineOption(%q) should return nil", tt.engineValue)
            } else {
                require.NotNil(t, result, "GetEngineOption(%q) should return a valid EngineOption", tt.engineValue)
                assert.Equal(t, tt.wantValue, result.Value, "EngineOption.Value should match input")
            }
        })
    }
}
3. Improve assertion messages on table-driven tests

Several table-driven tests omit assertion messages, making failures hard to debug. The inner t.Run(tt.name, ...) subtest name is shown, but enriched messages help identify exactly what went wrong.

Current (missing message):

// In TestConstantValues
t.Run(tt.name, func(t *testing.T) {
    if tt.value != tt.expected {
        t.Errorf("%s = %q, want %q", tt.name, tt.value, tt.expected)
    }
})

Recommended:

t.Run(tt.name, func(t *testing.T) {
    assert.Equal(t, tt.expected, tt.value, "constant %s should have expected value", tt.name)
})

Current (missing message):

// In TestGetIntFromEnv
if result != tt.expected {
    t.Errorf("Expected %d, got %d", tt.expected, result)
}

Recommended:

assert.Equal(t, tt.expected, result, "test case %q: GetIntFromEnv(%q, %d, %d, %d) should return %d",
    tt.name, tt.envValue, tt.defaultValue, tt.minValue, tt.maxValue, tt.expected)
4. Refactor repetitive non-table-driven tests

TestSemanticTypeAliases and TestTypeSafetyBetweenSemanticTypes have deeply nested t.Run() blocks with repeated conversion-check patterns that could be consolidated.

Current — each subtype has its own block with the same 3-line pattern:

t.Run("URL type", func(t *testing.T) {
    var testURL URL = "(example.com/redacted)"
    if string(testURL) != "(example.com/redacted)" {
        t.Errorf("URL conversion failed: got %q, want %q", testURL, "(example.com/redacted)")
    }
    ...
})
t.Run("ModelName type", func(t *testing.T) {
    var testModel ModelName = "test-model"
    if string(testModel) != "test-model" {
        t.Errorf("ModelName conversion failed: got %q, want %q", testModel, "test-model")
    }
    ...
})

These subtests within TestSemanticTypeAliases and TestHelperMethods repeat the same String() / IsValid() pattern for 9 different types. While each type needs distinct constant validation, the structural repetition suggests the conversion tests could be merged into TestHelperMethods, which already covers String() and IsValid() for all the same types.

5. Use assert.ElementsMatch for unordered slice checks

TestDefaultAllowedDomains, TestSafeWorkflowEvents, and TestAgenticEngines check specific element ordering. If the slice order is not guaranteed by the API contract, assert.ElementsMatch is safer than index-based checks.

Current:

for i, domain := range expectedDomains {
    if DefaultAllowedDomains[i] != domain {
        t.Errorf("DefaultAllowedDomains[%d] = %q, want %q", i, DefaultAllowedDomains[i], domain)
    }
}

Recommended (if order is not contractual):

assert.ElementsMatch(t, expectedDomains, DefaultAllowedDomains,
    "DefaultAllowedDomains should contain exactly the expected domains")

Or if order IS contractual:

assert.Equal(t, expectedDomains, DefaultAllowedDomains,
    "DefaultAllowedDomains should contain domains in specified order")

Implementation Guidelines

Priority Order

  1. High: Add TestGetEngineOption — the only untested exported function
  2. High: Convert t.Errorf / t.Error to assert.Equal / assert.NotEmpty / require.NoError
  3. Medium: Add informative assertion messages to table-driven tests
  4. Low: Evaluate whether TestSemanticTypeAliases subtype conversion tests overlap with TestHelperMethods and consolidate

Required Import

Add testify imports at the top of the file:

import (
    "path/filepath"
    "testing"
    "time"

    "github.com/stretchr/testify/assert"
    "github.com/stretchr/testify/require"
)

Best Practices from scratchpad/testing.md

  • ✅ Use require.* for critical setup (stops test on failure)
  • ✅ Use assert.* for test validations (continues checking)
  • ✅ Write table-driven tests with t.Run() and descriptive names
  • ✅ Always include helpful assertion messages

Testing Commands

# Run tests for this package
go test -v ./pkg/constants/ -run "TestConstants"

# Run with coverage
go test -cover ./pkg/constants/

# Run all unit tests before committing
make test-unit

Acceptance Criteria

  • Add github.com/stretchr/testify/assert and require imports
  • All 153 t.Errorf / t.Error calls replaced with appropriate testify assertions
  • New TestGetEngineOption test covers: valid engines, unknown engine (nil), empty string (nil), case sensitivity
  • All table-driven test assertions include descriptive messages
  • All tests pass: make test-unit
  • No new linter warnings: make lint
  • Code follows patterns in scratchpad/testing.md

Additional Context

  • Repository Testing Guidelines: See scratchpad/testing.md for comprehensive testing patterns
  • Example Tests: Look at pkg/envutil/envutil_test.go in this same analysis batch for a well-structured example (uses table-driven tests with good coverage)
  • Testify Documentation: https://github.com/stretchr/testify

Priority: Medium
Effort: Medium (738-line file, mechanical conversion + one new test function)
Expected Impact: Clearer test failure messages, standard testify patterns, coverage of GetEngineOption

Files Involved:

  • Test file: ./pkg/constants/constants_test.go
  • Source file: ./pkg/constants/constants.go

References:

Generated by Daily Testify Uber Super Expert

  • expires on Feb 23, 2026, 3:06 PM UTC

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions