Skip to content

[testify-expert] Improve Test Quality: pkg/cli/deps_test.go #37894

@github-actions

Description

@github-actions

Overview

The test file pkg/cli/deps_test.go tests the dependency health-checking subsystem but has zero testify assertions and significant coverage gaps across 10 of 17 source functions.

Current State

  • Test File: pkg/cli/deps_test.go (256 lines, 8 test functions)
  • Source Files: deps_go_mod.go, deps_outdated.go, deps_report.go, deps_security.go
  • Source Functions: 17 total — 7 tested, 10 untested

Strengths ✅

  1. Five tests already use table-driven tests []struct + t.Run() pattern.
  2. Helper functions correctly call t.Helper().
  3. TestFormatAge has good boundary coverage (zero, one, edge values).

Areas for Improvement 🎯

1. No Testify Assertions (Critical)

The file imports only "os", "strings", "testing", "time"no testify. Every assertion uses raw t.Errorf/t.Fatalf, contrary to the codebase standard documented in scratchpad/testing.md.

// ❌ CURRENT — throughout the whole file
if err != nil {
    t.Fatalf("parseGoMod() error = %v", err)
}
if len(deps) != 2 {
    t.Errorf("parseGoMod() found %d dependencies, want 2", len(deps))
}

// ✅ IMPROVED
require.NoError(t, err, "parseGoMod should parse valid go.mod without error")
require.Len(t, deps, 2, "should return only direct dependencies")
assert.Equal(t, "github.com/spf13/cobra", deps[0].Path)
assert.Equal(t, "v1.7.0", deps[0].Version)

2. Missing Assertion Messages

No assertions include context messages. Adding a message as the third argument makes failures self-explanatory without reading source.

// ✅ Add messages to all assertions
assert.Equal(t, tt.expected, result, "formatAge should format %d days correctly", tt.days)
require.NoError(t, err, "temp file write should succeed")

3. TestSeverityWeight — Use Table + Explicit Values

// ❌ CURRENT — manual comparisons
if severityWeight("critical") <= severityWeight("high") {
    t.Error("critical should have higher weight than high")
}

// ✅ IMPROVED — explicit expected values, catches regressions in exact weights
tests := []struct{ severity string; expected int }{
    {"critical", 4}, {"high", 3}, {"medium", 2}, {"low", 1}, {"", 0},
}
for _, tt := range tests {
    t.Run(tt.severity, func(t *testing.T) {
        assert.Equal(t, tt.expected, severityWeight(tt.severity),
            "severityWeight(%q) should return correct weight", tt.severity)
    })
}

4. Temp File Handling — Use t.TempDir()

// ❌ CURRENT — manual helpers; removeTempFile is noisy and fragile
tmpFile := createTempFile(t, goModContent)
defer removeTempFile(t, tmpFile)

// ✅ IMPROVED — t.TempDir() auto-cleans even on panic
tmpDir := t.TempDir()
tmpFile := filepath.Join(tmpDir, "go.mod")
err := os.WriteFile(tmpFile, []byte(goModContent), 0600)
require.NoError(t, err, "should write temp go.mod file")

5. TestGetUpdateStatus — Incomplete Assertion

The non-v0 case only checks strings.Contains(result, "Update available"), which would also pass if the v0 warning appeared incorrectly. Use assert.Equal for exact matching:

// ✅ IMPROVED
tests := []struct{ name string; dep OutdatedDependency; want string }{
    {"non-v0", OutdatedDependency{IsV0: false}, "Update available"},
    {"v0.x",   OutdatedDependency{IsV0: true},  "Update available ⚠️ v0.x"},
}
for _, tt := range tests {
    t.Run(tt.name, func(t *testing.T) {
        assert.Equal(t, tt.want, getUpdateStatus(tt.dep),
            "getUpdateStatus should return correct status")
    })
}

Coverage Gaps 📋

10 functions have no tests. Priority non-network functions:

Function Why Important
DisplayDependencyReportJSON Pure output — easy to test with stdout capture + JSON parse
DisplayOutdatedDependencies Table rendering — test empty/non-empty cases
DisplaySecurityAdvisories Severity sorting — test ordering behavior
findGoMod Path discovery — use t.Chdir() to set up working dir
DisplayDependencyReport High-level report — test with DependencyReport struct

Network-dependent functions (getLatestVersion, querySecurityAdvisories, CheckOutdatedDependencies, CheckSecurityAdvisories, GenerateDependencyReport) should use httptest.NewServer or //go:build integration tags.

Acceptance Criteria

  • Import "github.com/stretchr/testify/assert" and "github.com/stretchr/testify/require"
  • Replace all t.Errorf/t.Fatalf/t.Error with assert.*/require.* equivalents
  • Add descriptive message arguments to all assertions
  • Refactor TestSeverityWeight to table-driven with explicit expected values
  • Replace createTempFile/removeTempFile helpers with t.TempDir()
  • Use assert.Equal in TestGetUpdateStatus (not strings.Contains)
  • Add tests for DisplayDependencyReportJSON (stdout-capture pattern)
  • Add tests for DisplayOutdatedDependencies (stderr-capture pattern)
  • Tests pass: make test-unit
  • Follows patterns in scratchpad/testing.md

Additional Context


Priority: Medium | Effort: Small (testify migration) + Medium (coverage)

References:

Generated by 🧪 Daily Testify Uber Super Expert · ⌖ 28.5 AIC · ⊞ 21.5K ·

  • expires on Jun 10, 2026, 10:48 AM UTC-08:00

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions