Testing Strategies to Validate Go Modern Guidelines Across Different Go Versions

The JetBrains/go-modern-guidelines repository validates guideline correctness through a multi-layered test suite that combines version-aware filtering, robust Go version resolution, and strict JSON schema validation.

The go-modern-guidelines project maintains a curated set of best practices that evolve with each Go release. To ensure recommendations remain accurate across Go 1.24 through 1.27 and beyond, the repository implements comprehensive testing strategies that verify guideline applicability, version detection logic, and data integrity. These tests guarantee that developers receive only relevant advice when running the tool against different Go versions.

Version-Aware Guideline Selection

The core challenge involves determining which guidelines apply to a specific Go version. The repository solves this through dynamic filtering backed by rigorous unit tests.

Filtering by Target Version

In internal/guidelines/guidelines.go, the supportedGuidelines function uses goversion.Compare to filter the embedded modernGoGuidelines slice. This ensures only guidelines with SinceVersion ≤ targetVersion are included in results.

The test file internal/guidelines/guidelines_test.go contains TestListForResolvedVersion and TestListForGo127, which verify that ListText returns a newest-first list for requested versions like 1.26 and 1.27. These tests assert that older guidelines never appear before newer ones, maintaining the expected priority order.

Validating Version Constraints

The selection logic handles edge cases where guidelines introduce breaking changes or deprecations. Tests confirm that when a user targets Go 1.25, they do not see guidelines requiring Go 1.26 features, while users on Go 1.27 receive the complete applicable set.

Robust Go Version Resolution

Accurate guideline selection depends on correctly identifying the active Go version from diverse sources, including module files and environment strings.

Normalizing Diverse Version Strings

The internal/goversion/goversion.go file implements normalization and comparison logic that handles inputs like 1.24, go1.24.3, Go1.25, and the special devel identifier with user-supplied fallbacks.

Tests in internal/goversion/goversion_test.go cover:

  • Normalization: Converting various prefix formats to canonical versions
  • Comparison semantics: Handling major/minor boundaries correctly (e.g., 1.9 vs 1.10, 2.0 vs 1.99)
  • Format detection: Validating IsMajorMinor checks

Resolving from Module Files

The Resolve function extracts the go directive from go.mod and go.work files, including error handling for malformed directives. The TestResolveFromNearestGoMod test simulates temporary module hierarchies to confirm that the nearest go.mod influences version resolution correctly.

// Resolve the Go version for a source file, falling back to the local toolchain.
v, err := goversion.Resolve("path/to/file.go", "", "1.27")
if err != nil {
    log.Fatal(err)
}
fmt.Println("Using Go version:", v) // → e.g. "1.26"

Schema Validation for Guideline Integrity

Guidelines are stored as JSON and parsed by the schema package. Strict validation prevents corrupted or inconsistent data from reaching users.

Enforcing Field Constraints

The internal/guidelines/schema/schema_test.go suite includes TestParseValidGuidelines and TestParseRejectsInvalidGuideline, which check:

  • Rejection of unsafe IDs
  • Validation of major/minor version formats
  • Presence of required modernizer flags
  • Non-empty text fields

Detecting Structural Violations

Additional tests verify ordering constraints and uniqueness:

  • TestParseRejectsDuplicateIDs ensures no two guidelines share the same identifier
  • Ordering validation confirms guidelines remain sorted newest-first
  • Error messages are asserted to contain clear diagnostics for rapid debugging
// Parse and validate a new guideline definition.
data := []byte(`[{"id":"example","since_version":"1.28","modernizer":true,"category":"Security","impact":"High","guideline":"Use x","details":"Details","examples":[{"before":["old"],"after":["new"]}]}]`)
guidelines, err := schema.Parse(data)
if err != nil {
    log.Fatalf("invalid guideline: %v", err)
}
fmt.Printf("Loaded %d guideline(s)\n", len(guidelines))

Integration and CLI Safeguards

Beyond core logic, the test suite protects against documentation drift and command-line ambiguity.

Documentation Synchronization

The internal/guidelines/featuresgen/main_test.go file contains TestFeaturesMarkdownInSync, which regenerates FEATURES.md from guidelines.json and verifies byte-for-byte equality. This prevents documentation from describing features that no longer exist or omitting newly added guidelines.

CLI Argument Validation

The internal/cli/cli_test.go suite confirms that conflicting version-source flags are rejected, preventing ambiguous version resolution. These tests ensure users cannot simultaneously specify a version via --go-version and --go-mod-path without clear precedence rules.

// List the guidelines that apply to Go 1.27 or newer.
fmt.Println(guidelines.ListText("1.27"))
// Output (truncated):
// generic_methods: Use generic methods instead of package-level helpers.
// promoted_field_literals: Set embedded struct fields directly …

Summary

The repository employs a defense-in-depth approach to testing strategies that validate guideline correctness across different Go versions:

  • Version-aware selection filters guidelines using goversion.Compare in supportedGuidelines, verified by guidelines_test.go
  • Version resolution normalizes diverse version strings and extracts values from go.mod/go.work, tested in goversion_test.go
  • Schema integrity enforces strict JSON validation through schema_test.go, catching duplicates and malformed entries
  • Documentation sync via featuresgen/main_test.go ensures FEATURES.md reflects the actual guideline set
  • CLI robustness in cli_test.go prevents ambiguous version-source configurations

Frequently Asked Questions

How does the repository determine which Go version to use for validation?

The goversion.Resolve function in internal/goversion/goversion.go checks multiple sources in priority order: explicit CLI flags, the nearest go.mod or go.work file, and finally the local toolchain. Tests in TestResolveFromNearestGoMod verify this hierarchy using temporary module hierarchies.

What prevents invalid guideline definitions from being merged?

The schema_test.go suite validates every field in guidelines.json through tests like TestParseRejectsInvalidGuideline. These catch unsafe IDs, non-conforming version strings, missing modernizer flags, and empty text fields before they reach production.

How are version strings like "go1.24.3" or "devel" handled during testing?

goversion_test.go includes TestNormalizeGoVersion cases that strip prefixes (e.g., "go", "Go"), handle patch versions, and substitute fallbacks for the special devel identifier. Comparison tests verify correct ordering across major and minor boundaries.

Where are the tests for CLI version-source conflicts located?

Argument Validation logic resides in internal/cli/cli_test.go, which ensures mutually exclusive flags (such as specifying both a direct version and a module file path) trigger clear errors, preventing ambiguous resolution behavior.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →