Skip to content

[testify-expert] Improve Test Quality: pkg/parser/json_path_locator_test.go #22139

@github-actions

Description

@github-actions

The test files pkg/parser/json_path_locator_test.go and pkg/parser/json_path_locator_improvements_test.go have been selected for quality improvement. Both files test the JSON path location logic in pkg/parser/json_path_locator.go but rely entirely on raw Go testing patterns instead of using the testify assertion library that is already available (github.com/stretchr/testify v1.11.1) and used extensively in the same package.

Current State

  • Primary Test File: pkg/parser/json_path_locator_test.go (251 lines)
  • Secondary Test File: pkg/parser/json_path_locator_improvements_test.go (499 lines)
  • Source File: pkg/parser/json_path_locator.go (451 lines)
  • Test Functions (primary): 3 (TestLocateJSONPathInYAML, TestExtractJSONPathFromValidationError, TestParseJSONPath)
  • Test Functions (secondary): 5 (TestExtractAdditionalPropertyNames, TestFindFirstAdditionalProperty, TestLocateJSONPathInYAMLWithAdditionalProperties, TestLocateJSONPathInYAMLWithAdditionalPropertiesNested, TestNestedSearchOptimization)
  • Testify Usage: 0 assertions in either file

Strengths ✅

  • Good use of table-driven tests with t.Run() subtests throughout both files
  • Comprehensive test scenarios covering valid inputs, invalid paths, edge cases, and nested structures
  • Well-organized test cases with clear names describing the scenario being tested
🎯 Areas for Improvement

1. Replace Raw Error Checks with Testify Assertions

Every assertion across both files uses raw t.Errorf / t.Fatalf patterns that should be replaced with testify equivalents.

Current pattern (appears ~50 times across both files):

if location.Found != tt.shouldFind {
    t.Errorf("Expected Found=%v, got Found=%v", tt.shouldFind, location.Found)
}

if location.Line != tt.expectedLine {
    t.Errorf("Expected Line=%d, got Line=%d", tt.expectedLine, location.Line)
}

if location.Column != tt.expectedCol {
    t.Errorf("Expected Column=%d, got Column=%d", tt.expectedCol, location.Column)
}

Recommended replacement:

assert.Equal(t, tt.shouldFind, location.Found, "location found flag should match expected")
assert.Equal(t, tt.expectedLine, location.Line, "line number should match expected")
assert.Equal(t, tt.expectedCol, location.Column, "column number should match expected")

2. Replace Fatal Checks with require

In TestExtractJSONPathFromValidationError, critical setup failures use raw t.Fatalf:

Current pattern:

schema, err := compiler.Compile(schemaURL)
if err != nil {
    t.Fatalf("Schema compilation error: %v", err)
}

err = schema.Validate(invalidData)
if err == nil {
    t.Fatal("Expected validation error, got nil")
}

Recommended replacement:

schema, err := compiler.Compile(schemaURL)
require.NoError(t, err, "schema should compile without errors")

err = schema.Validate(invalidData)
require.Error(t, err, "invalid data should fail schema validation")

3. Replace Manual Error Unmarshalling Check

In TestExtractJSONPathFromValidationError, the json.Unmarshal error is silently ignored:

Current pattern:

var schemaDoc any
json.Unmarshal([]byte(schemaJSON), &schemaDoc)  // error ignored!

Recommended replacement:

var schemaDoc any
err := json.Unmarshal([]byte(schemaJSON), &schemaDoc)
require.NoError(t, err, "test schema JSON should be valid")

4. Simplify Length Check + Element Iteration Pattern

In TestExtractJSONPathFromValidationError and TestExtractAdditionalPropertyNames, the pattern of checking length and then iterating manually can be replaced:

Current pattern:

if len(paths) != 3 {
    t.Errorf("Expected 3 validation errors, got %d", len(paths))
}

Recommended replacement:

require.Len(t, paths, 3, "should extract exactly 3 validation error paths")

For TestExtractAdditionalPropertyNames, the element comparison:

// ❌ Current
if len(result) != len(tt.expected) {
    t.Errorf("Expected %d properties, got %d: %v", len(tt.expected), len(result), result)
    return
}
for i, expected := range tt.expected {
    if i >= len(result) || result[i] != expected {
        t.Errorf("Expected property %d to be '%s', got '%s'", i, expected, result[i])
    }
}

// ✅ Recommended
require.Len(t, result, len(tt.expected), "property count should match")
assert.Equal(t, tt.expected, result, "extracted properties should match expected")

5. Improve Segment Comparison in TestParseJSONPath

Current pattern:

if len(result) != len(tt.expected) {
    t.Errorf("Expected %d segments, got %d", len(tt.expected), len(result))
    return
}
for i, expected := range tt.expected {
    if result[i].Type != expected.Type {
        t.Errorf("Segment %d: expected Type=%s, got Type=%s", i, expected.Type, result[i].Type)
    }
    if result[i].Value != expected.Value {
        t.Errorf("Segment %d: expected Value=%s, got Value=%s", i, expected.Value, result[i].Value)
    }
    if expected.Type == "index" && result[i].Index != expected.Index {
        t.Errorf("Segment %d: expected Index=%d, got Index=%d", i, expected.Index, result[i].Index)
    }
}

Recommended replacement:

require.Len(t, result, len(tt.expected), "number of path segments should match")
assert.Equal(t, tt.expected, result, "parsed path segments should match expected")

Since PathSegment is a simple struct with comparable fields, assert.Equal can deep-compare the full slice at once, producing clear diff output on failure.

6. Add Missing Imports

Both files need testify imports added:

import (
    "testing"
    
    "github.com/stretchr/testify/assert"
    "github.com/stretchr/testify/require"
    // ... existing imports
)
📋 Example Refactored Test Function

Here's TestLocateJSONPathInYAML fully refactored:

func TestLocateJSONPathInYAML(t *testing.T) {
    yamlContent := `name: John Doe
age: 30
tools:
  - name: tool1
    version: "1.0"
  - name: tool2
    description: "second tool"
permissions:
  read: true
  write: false`

    tests := []struct {
        name       string
        jsonPath   string
        expectLine int
        expectCol  int
        shouldFind bool
    }{
        {
            name:       "root level",
            jsonPath:   "",
            expectLine: 1,
            expectCol:  1,
            shouldFind: true,
        },
        {
            name:       "simple key",
            jsonPath:   "/name",
            expectLine: 1,
            expectCol:  6,
            shouldFind: true,
        },
        // ... remaining cases
    }

    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            location := LocateJSONPathInYAML(yamlContent, tt.jsonPath)

            assert.Equal(t, tt.shouldFind, location.Found, "Found flag should match expected for path %q", tt.jsonPath)
            assert.Equal(t, tt.expectLine, location.Line, "Line should match expected for path %q", tt.jsonPath)
            assert.Equal(t, tt.expectCol, location.Column, "Column should match expected for path %q", tt.jsonPath)
        })
    }
}

Acceptance Criteria

  • Add github.com/stretchr/testify/assert and require imports to both test files
  • Replace all if X != Y { t.Errorf(...) } with assert.Equal(t, expected, actual, "message")
  • Replace all if err != nil { t.Fatalf(...) } with require.NoError(t, err, "message")
  • Replace all if err == nil { t.Fatal(...) } with require.Error(t, err, "message")
  • Fix silently-ignored json.Unmarshal error using require.NoError
  • Replace manual length+element checks with require.Len + assert.Equal (slice comparison)
  • All assertions include descriptive failure messages
  • Tests pass: go test -v ./pkg/parser/ -run "TestLocateJSONPath|TestExtractJSONPath|TestParseJSONPath|TestExtractAdditional|TestFindFirst|TestFindFrontmatter|TestNestedSearch"

Testing Commands

# Run just these tests
go test -v ./pkg/parser/ -run "TestLocateJSONPath|TestExtractJSONPath|TestParseJSONPath|TestExtractAdditional|TestFindFirst|TestFindFrontmatter|TestNestedSearch"

# Run all parser tests
go test -v ./pkg/parser/

# Full validation
make test-unit

Additional Context

  • Testify version: github.com/stretchr/testify v1.11.1 (already in go.mod)
  • Good example in same package: pkg/parser/frontmatter_helpers_test.go uses assert/require correctly
  • Repository testing guidelines: See scratchpad/testing.md

Priority: Medium
Effort: Small (mechanical substitution, ~750 lines across 2 files)
Expected Impact: Clearer test failure messages, consistent style, easier maintenance

Files Involved:

  • pkg/parser/json_path_locator_test.go
  • pkg/parser/json_path_locator_improvements_test.go
  • Source: pkg/parser/json_path_locator.go

References: §23382255786

Generated by Daily Testify Uber Super Expert ·

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

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