testalign

package module
v0.0.0-...-2df69d2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 8, 2026 License: MIT Imports: 7 Imported by: 0

README

go-testalign

A Go static analysis tool that verifies test function order matches the declaration order of the corresponding source functions.

Motivation

When test functions are ordered differently from their corresponding source functions, navigating between implementation and tests becomes harder. go-testalign detects this misalignment and reports it, helping keep your test files consistent and easy to follow.

Installation

go install github.com/basashifx/go-testalign/cmd/go-testalign@latest

Usage

go-testalign ./...

Example

Given a source file:

// service.go
package service

type Service struct{}

func (s *Service) Create() error { return nil }
func (s *Service) Read() error   { return nil }
func (s *Service) Delete() error { return nil }

And a test file with mismatched order:

// service_test.go
package service

func TestService_Delete(t *testing.T) {}
func TestService_Create(t *testing.T) {}
func TestService_Read(t *testing.T) {}

go-testalign reports:

service_test.go:5:1: TestService_Create corresponds to Service.Create (service.go:5) but appears before TestService_Delete which corresponds to Service.Delete (service.go:7)
service_test.go:6:1: TestService_Read corresponds to Service.Read (service.go:6) but appears before TestService_Delete which corresponds to Service.Delete (service.go:7)

How it works

Test-to-source matching

go-testalign strips the test prefix (Test, Benchmark, Fuzz, Example) and matches the remaining name against source functions:

Test function Matched source
TestService_Create (s *Service) Create()
TestService_Create_Success (s *Service) Create() (subtest, longest prefix match)
TestMyFunc func MyFunc()
Test_helper func helper()

Unmatched test functions (e.g. TestIntegration, test helpers) are silently skipped.

File pairing

Test files are paired with source files by naming convention: foo_test.go checks against foo.go. If no matching source file exists, all source functions in the package are used.

Order verification

For each test file, the tool assigns source declaration indices to matched test functions and verifies the sequence is monotonically non-decreasing. A violation is reported when a test function's source appears earlier than the source of a preceding test.

External test packages

For external test packages (package foo_test), source function order is communicated via analysis.Fact, so the tool works correctly even when the test package is separate from the source package.

Supported patterns

  • Methods with pointer and value receivers
  • Generic types (Container[T], Pair[K, V])
  • Subtest naming (TestFoo_Success, TestFoo_Error)
  • Unexported functions (Test_helper -> helper())
  • Multiple source files per package
  • Multiple receiver types in a single file
  • Test, Benchmark, Fuzz, and Example prefixes
  • External test packages (package foo_test)

Requirements

  • Go 1.22 or later

License

MIT

Documentation

Index

Constants

This section is empty.

Variables

View Source
var Analyzer = &analysis.Analyzer{
	Name: "testalign",
	Doc:  "テスト関数の順序がソースコードの宣言順序と一致しているかを検証する",
	Run:  run,
	FactTypes: []analysis.Fact{
		(*SourceOrderFact)(nil),
	},
}

Analyzer はテスト関数の順序がソースコードの宣言順序と一致しているかを検証する。

Functions

func IsTestFile

func IsTestFile(filename string) bool

IsTestFile はファイル名がテストファイルかどうかを判定する。

func SourceFileForTest

func SourceFileForTest(testFile string) string

SourceFileForTest はテストファイルに対応するソースファイル名を返す。 例: "foo_test.go" → "foo.go"

Types

type MatchResult

type MatchResult struct {
	TestFunc   TestFunc
	SourceFunc *SourceFunc // nilの場合は対応するソース関数なし
}

MatchResult はテスト関数とソース関数の対応を表す。

func MatchTestFuncs

func MatchTestFuncs(testFuncs []TestFunc, sourceFuncs []SourceFunc) []MatchResult

MatchTestFuncs はテスト関数をソース関数にマッチングする。 マッチングルール(優先度順): 1. 完全一致: TargetName == QualifiedName 2. サブテストマッチ: TargetNameがQualifiedName + "_"で始まる最長一致 3. マッチなしの場合はSourceFuncがnilのMatchResultを返す

type OrderViolation

type OrderViolation struct {
	TestFunc      TestFunc     // 順序違反のテスト関数
	SourceFunc    SourceFunc   // 対応するソース関数
	PrecedingTest *MatchResult // ソース順序的に後にあるべきテスト関数
}

OrderViolation は順序違反の情報を表す。

func DetectOrderViolations

func DetectOrderViolations(matches []MatchResult, sourceFuncs []SourceFunc) []OrderViolation

DetectOrderViolations はマッチ済みテスト関数の順序がソース関数の宣言順序と 一致しているかを検証し、違反箇所を返す。

ソース関数のインデックス列が単調非減少であることを検証する。 違反箇所: ソースインデックスがそれまでの最大値より小さい位置。

type SourceFunc

type SourceFunc struct {
	Name         string    // 関数名
	ReceiverType string    // レシーバー型名(関数の場合は空)
	Pos          token.Pos // 宣言位置
	FileName     string    // ファイル名
}

SourceFunc はソースファイル内の関数またはメソッド宣言を表す。

func ExtractSourceFuncs

func ExtractSourceFuncs(file *ast.File, fset *token.FileSet) []SourceFunc

ExtractSourceFuncs はASTファイルからソース関数/メソッドを抽出する。 init関数は除外される。

func (SourceFunc) QualifiedName

func (sf SourceFunc) QualifiedName() string

QualifiedName はレシーバー型を含む修飾名を返す。 メソッドの場合は "ReceiverType_Name"、関数の場合は "Name" を返す。 非公開関数の場合は "_name" の形式を返す。

type SourceOrderFact

type SourceOrderFact struct {
	FileToFuncs map[string][]SourceFunc
}

SourceOrderFact は外部テストパッケージ用のFactとしてエクスポートされる。 ソースファイルごとの関数一覧を保持する。

func (*SourceOrderFact) AFact

func (*SourceOrderFact) AFact()

func (*SourceOrderFact) String

func (*SourceOrderFact) String() string

type TestFunc

type TestFunc struct {
	Name     string    // テスト関数名(例: "TestService_Create")
	Pos      token.Pos // 宣言位置
	FileName string    // ファイル名
}

TestFunc はテストファイル内のテスト関数宣言を表す。

func ExtractTestFuncs

func ExtractTestFuncs(file *ast.File, fset *token.FileSet) []TestFunc

ExtractTestFuncs はASTファイルからテスト関数を抽出する。 Test*/Benchmark*/Fuzz*/Example* プレフィックスの関数のみ抽出する。

func (TestFunc) TargetName

func (tf TestFunc) TargetName() string

TargetName はテストプレフィックス(Test/Benchmark/Fuzz/Example)を除去した名前を返す。

Directories

Path Synopsis
cmd
go-testalign command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL