all repos

clerk @ 232cfaba8685839ee439fec29100e31822de2da4

missing tooling for ledger/hledger
107 files changed, 15 insertions(+), 44 deletions(-)
tests: unify golden test api and usage
Author: Oleksandr Smirnov olexsmir@gmail.com
Committed at: 2026-06-10 12:26:05 +0300
Authored at: 2026-06-10 12:20:43 +0300
Change ID: znopxttqsynqwszymmqurvlznlqqvmvq
Parent: 2d8dc1f
jump to
M internal/testutil/golden/golden.go
M journal/lexer/lexer_test.go
M journal/lexer/testdata/golden/Lexer__account_directive.golden → journal/lexer/testdata/account_directive.golden
M journal/lexer/testdata/golden/Lexer__automated_transaction.golden → journal/lexer/testdata/automated_transaction.golden
M journal/lexer/testdata/golden/Lexer__better_date.golden → journal/lexer/testdata/better_date.golden
M journal/lexer/testdata/golden/Lexer__blank_lines.golden → journal/lexer/testdata/blank_lines.golden
M journal/lexer/testdata/golden/Lexer__cleared_transaction.golden → journal/lexer/testdata/cleared_transaction.golden
M journal/lexer/testdata/golden/Lexer__comment_block_directive.golden → journal/lexer/testdata/comment_block_directive.golden
M journal/lexer/testdata/golden/Lexer__comment_block_directive_without_end.golden → journal/lexer/testdata/comment_block_directive_without_end.golden
M journal/lexer/testdata/golden/Lexer__comment_line.golden → journal/lexer/testdata/comment_line.golden
M journal/lexer/testdata/golden/Lexer__commodity_directive.golden → journal/lexer/testdata/commodity_directive.golden
M journal/lexer/testdata/golden/Lexer__date_with_secondary.golden → journal/lexer/testdata/date_with_secondary.golden
M journal/lexer/testdata/golden/Lexer__empty.golden → journal/lexer/testdata/empty.golden
M journal/lexer/testdata/golden/Lexer__hash_comment.golden → journal/lexer/testdata/hash_comment.golden
M journal/lexer/testdata/golden/Lexer__inline_comment.golden → journal/lexer/testdata/inline_comment.golden
M journal/lexer/testdata/golden/Lexer__market_price_directive.golden → journal/lexer/testdata/market_price_directive.golden
M journal/lexer/testdata/golden/Lexer__market_price_directive_with_time.golden → journal/lexer/testdata/market_price_directive_with_time.golden
M journal/lexer/testdata/golden/Lexer__simple_transaction.golden → journal/lexer/testdata/simple_transaction.golden
M journal/lexer/testdata/golden/Lexer__special_chars_in_description.golden → journal/lexer/testdata/special_chars_in_description.golden
M journal/lexer/testdata/golden/Lexer__star_comment.golden → journal/lexer/testdata/star_comment.golden
M journal/lexer/testdata/golden/Lexer__transaction,_accounts_with_uppercase_latters.golden → journal/lexer/testdata/transaction,_accounts_with_uppercase_latters.golden
M journal/lexer/testdata/golden/Lexer__transaction_with_code.golden → journal/lexer/testdata/transaction_with_code.golden
M journal/lexer/testdata/golden/Lexer__transaction_with_unicode_commodity_symbols.golden → journal/lexer/testdata/transaction_with_unicode_commodity_symbols.golden
M journal/lexer/testdata/golden/Lexer__transaction_with_virtual_accounts.golden → journal/lexer/testdata/transaction_with_virtual_accounts.golden
M journal/parser/parser_test.go
M journal/parser/testdata/golden/Parser_ParseFile__C_directive.golden → journal/parser/testdata/C_directive.golden
M journal/parser/testdata/golden/Parser_ParseFile__D_directive.golden → journal/parser/testdata/D_directive.golden
M journal/parser/testdata/golden/Parser_ParseFile__N_directive.golden → journal/parser/testdata/N_directive.golden
M journal/parser/testdata/golden/Parser_ParseFile__P_directive.golden → journal/parser/testdata/P_directive.golden
M journal/parser/testdata/golden/Parser_ParseFile__P_directive_with_time.golden → journal/parser/testdata/P_directive_with_time.golden
M journal/parser/testdata/golden/Parser_ParseFile__account_directive.golden → journal/parser/testdata/account_directive.golden
M journal/parser/testdata/golden/Parser_ParseFile__account_directive_with_comment.golden → journal/parser/testdata/account_directive_with_comment.golden
M journal/parser/testdata/golden/Parser_ParseFile__account_with_spaces.golden → journal/parser/testdata/account_with_spaces.golden
M journal/parser/testdata/golden/Parser_ParseFile__account_with_subdirectives.golden → journal/parser/testdata/account_with_subdirectives.golden
M journal/parser/testdata/golden/Parser_ParseFile__alias_directive.golden → journal/parser/testdata/alias_directive.golden
M journal/parser/testdata/golden/Parser_ParseFile__all_postings_bad.golden → journal/parser/testdata/all_postings_bad.golden
M journal/parser/testdata/golden/Parser_ParseFile__apply_fixed_directive.golden → journal/parser/testdata/apply_fixed_directive.golden
M journal/parser/testdata/golden/Parser_ParseFile__apply_tag_directive.golden → journal/parser/testdata/apply_tag_directive.golden
M journal/parser/testdata/golden/Parser_ParseFile__automated_transaction.golden → journal/parser/testdata/automated_transaction.golden
M journal/parser/testdata/golden/Parser_ParseFile__bad_between_good.golden → journal/parser/testdata/bad_between_good.golden
M journal/parser/testdata/golden/Parser_ParseFile__bad_posting_at_end.golden → journal/parser/testdata/bad_posting_at_end.golden
M journal/parser/testdata/golden/Parser_ParseFile__bad_then_next_transaction.golden → journal/parser/testdata/bad_then_next_transaction.golden
M journal/parser/testdata/golden/Parser_ParseFile__blank_line.golden → journal/parser/testdata/blank_line.golden
M journal/parser/testdata/golden/Parser_ParseFile__comment_between_bad_postings.golden → journal/parser/testdata/comment_between_bad_postings.golden
M journal/parser/testdata/golden/Parser_ParseFile__comment_directive.golden → journal/parser/testdata/comment_directive.golden
M journal/parser/testdata/golden/Parser_ParseFile__comment_directive_end_alone.golden → journal/parser/testdata/comment_directive_end_alone.golden
M journal/parser/testdata/golden/Parser_ParseFile__comment_directive_with_header.golden → journal/parser/testdata/comment_directive_with_header.golden
M journal/parser/testdata/golden/Parser_ParseFile__comment_hash.golden → journal/parser/testdata/comment_hash.golden
M journal/parser/testdata/golden/Parser_ParseFile__comment_percent.golden → journal/parser/testdata/comment_percent.golden
M journal/parser/testdata/golden/Parser_ParseFile__comment_semicolon.golden → journal/parser/testdata/comment_semicolon.golden
M journal/parser/testdata/golden/Parser_ParseFile__comment_star.golden → journal/parser/testdata/comment_star.golden
M journal/parser/testdata/golden/Parser_ParseFile__commodity_quantity_after.golden → journal/parser/testdata/commodity_quantity_after.golden
M journal/parser/testdata/golden/Parser_ParseFile__commodity_quantity_first.golden → journal/parser/testdata/commodity_quantity_first.golden
M journal/parser/testdata/golden/Parser_ParseFile__commodity_with_subdirectives.golden → journal/parser/testdata/commodity_with_subdirectives.golden
M journal/parser/testdata/golden/Parser_ParseFile__comodity_directive.golden → journal/parser/testdata/comodity_directive.golden
M journal/parser/testdata/golden/Parser_ParseFile__comodity_directive_no_space.golden → journal/parser/testdata/comodity_directive_no_space.golden
M journal/parser/testdata/golden/Parser_ParseFile__comodity_directive_word.golden → journal/parser/testdata/comodity_directive_word.golden
M journal/parser/testdata/golden/Parser_ParseFile__decimal-mark_directive.golden → journal/parser/testdata/decimal-mark_directive.golden
M journal/parser/testdata/golden/Parser_ParseFile__digit_group_marks.golden → journal/parser/testdata/digit_group_marks.golden
M journal/parser/testdata/golden/Parser_ParseFile__directive_prefixes.golden → journal/parser/testdata/directive_prefixes.golden
M journal/parser/testdata/golden/Parser_ParseFile__empty_comment_block.golden → journal/parser/testdata/empty_comment_block.golden
M journal/parser/testdata/golden/Parser_ParseFile__end_apply_directive.golden → journal/parser/testdata/end_apply_directive.golden
M journal/parser/testdata/golden/Parser_ParseFile__illegal_at_start.golden → journal/parser/testdata/illegal_at_start.golden
M journal/parser/testdata/golden/Parser_ParseFile__illegal_between_transactions.golden → journal/parser/testdata/illegal_between_transactions.golden
M journal/parser/testdata/golden/Parser_ParseFile__illegal_in_posting.golden → journal/parser/testdata/illegal_in_posting.golden
M journal/parser/testdata/golden/Parser_ParseFile__illegal_only.golden → journal/parser/testdata/illegal_only.golden
M journal/parser/testdata/golden/Parser_ParseFile__inclue_directive.golden → journal/parser/testdata/inclue_directive.golden
M journal/parser/testdata/golden/Parser_ParseFile__inclue_directive_with_comment.golden → journal/parser/testdata/inclue_directive_with_comment.golden
M journal/parser/testdata/golden/Parser_ParseFile__multiple_bad_postings.golden → journal/parser/testdata/multiple_bad_postings.golden
M journal/parser/testdata/golden/Parser_ParseFile__nested_apply_tag_directives.golden → journal/parser/testdata/nested_apply_tag_directives.golden
M journal/parser/testdata/golden/Parser_ParseFile__never_ending_comment_directive.golden → journal/parser/testdata/never_ending_comment_directive.golden
M journal/parser/testdata/golden/Parser_ParseFile__payee_directive.golden → journal/parser/testdata/payee_directive.golden
M journal/parser/testdata/golden/Parser_ParseFile__period_transaction_expressions.golden → journal/parser/testdata/period_transaction_expressions.golden
M journal/parser/testdata/golden/Parser_ParseFile__quoted_payee_names.golden → journal/parser/testdata/quoted_payee_names.golden
M journal/parser/testdata/golden/Parser_ParseFile__recovery_after_bad_posting.golden → journal/parser/testdata/recovery_after_bad_posting.golden
M journal/parser/testdata/golden/Parser_ParseFile__special_chars_in_description.golden → journal/parser/testdata/special_chars_in_description.golden
M journal/parser/testdata/golden/Parser_ParseFile__tag_directive.golden → journal/parser/testdata/tag_directive.golden
M journal/parser/testdata/golden/Parser_ParseFile__three_bad_postings.golden → journal/parser/testdata/three_bad_postings.golden
M journal/parser/testdata/golden/Parser_ParseFile__transaction.golden → journal/parser/testdata/transaction.golden
M journal/parser/testdata/golden/Parser_ParseFile__transaction_clearerd.golden → journal/parser/testdata/transaction_clearerd.golden
M journal/parser/testdata/golden/Parser_ParseFile__transaction_in_ukrainian.golden → journal/parser/testdata/transaction_in_ukrainian.golden
M journal/parser/testdata/golden/Parser_ParseFile__transaction_pending.golden → journal/parser/testdata/transaction_pending.golden
M journal/parser/testdata/golden/Parser_ParseFile__transaction_with_balance_assertion.golden → journal/parser/testdata/transaction_with_balance_assertion.golden
M journal/parser/testdata/golden/Parser_ParseFile__transaction_with_code.golden → journal/parser/testdata/transaction_with_code.golden
M journal/parser/testdata/golden/Parser_ParseFile__transaction_with_comment.golden → journal/parser/testdata/transaction_with_comment.golden
M journal/parser/testdata/golden/Parser_ParseFile__transaction_with_cost_and_assertion.golden → journal/parser/testdata/transaction_with_cost_and_assertion.golden
M journal/parser/testdata/golden/Parser_ParseFile__transaction_with_costs.golden → journal/parser/testdata/transaction_with_costs.golden
M journal/parser/testdata/golden/Parser_ParseFile__transaction_with_digit_payees.golden → journal/parser/testdata/transaction_with_digit_payees.golden
M journal/parser/testdata/golden/Parser_ParseFile__transaction_with_header_comment.golden → journal/parser/testdata/transaction_with_header_comment.golden
M journal/parser/testdata/golden/Parser_ParseFile__transaction_with_inline_comment.golden → journal/parser/testdata/transaction_with_inline_comment.golden
M journal/parser/testdata/golden/Parser_ParseFile__transaction_with_multiword_payee.golden → journal/parser/testdata/transaction_with_multiword_payee.golden
M journal/parser/testdata/golden/Parser_ParseFile__transaction_with_note.golden → journal/parser/testdata/transaction_with_note.golden
M journal/parser/testdata/golden/Parser_ParseFile__transaction_with_payee.golden → journal/parser/testdata/transaction_with_payee.golden
M journal/parser/testdata/golden/Parser_ParseFile__transaction_with_posting.golden → journal/parser/testdata/transaction_with_posting.golden
M journal/parser/testdata/golden/Parser_ParseFile__transaction_with_posting_amounts.golden → journal/parser/testdata/transaction_with_posting_amounts.golden
M journal/parser/testdata/golden/Parser_ParseFile__transaction_with_secondary_date.golden → journal/parser/testdata/transaction_with_secondary_date.golden
M journal/parser/testdata/golden/Parser_ParseFile__transaction_with_spaced_account_name.golden → journal/parser/testdata/transaction_with_spaced_account_name.golden
M journal/parser/testdata/golden/Parser_ParseFile__transaction_with_strange_commodity_symbols.golden → journal/parser/testdata/transaction_with_strange_commodity_symbols.golden
M journal/parser/testdata/golden/Parser_ParseFile__transaction_with_tabs.golden → journal/parser/testdata/transaction_with_tabs.golden
M journal/parser/testdata/golden/Parser_ParseFile__transaction_with_trailing_indent.golden → journal/parser/testdata/transaction_with_trailing_indent.golden
M journal/parser/testdata/golden/Parser_ParseFile__transaction_with_unicode_commodity_symbols.golden → journal/parser/testdata/transaction_with_unicode_commodity_symbols.golden
M journal/parser/testdata/golden/Parser_ParseFile__transaction_with_virtual_accounts.golden → journal/parser/testdata/transaction_with_virtual_accounts.golden
M journal/parser/testdata/golden/Parser_ParseFile__unexpected_token.golden → journal/parser/testdata/unexpected_token.golden
M journal/parser/testdata/golden/Parser_ParseFile__virtual_postings_with_statuses.golden → journal/parser/testdata/virtual_postings_with_statuses.golden
M journal/parser/testdata/golden/Parser_ParseFile__year_directive.golden → journal/parser/testdata/year_directive.golden
M journal/printer/printer_test.go
M journal/tags/tag_test.go
M internal/testutil/golden/golden.go
···
        10
        10
         

      
        11
        11
         var update = flag.Bool("golden.update", false, "update golden files")

      
        12
        12
         

      
        13
        
        -// Load reads testdata/<name>.input. Fails the test if the file is missing.

      
        14
        
        -func Load(t testing.TB, name string) []byte {

      
        
        13
        +// Load reads testdata/<path>.input. Fails the test if file is not found.

      
        
        14
        +func Load(t testing.TB, path string) []byte {

      
        15
        15
         	t.Helper()

      
        16
        
        -	path := filepath.Join("testdata", name+".input")

      
        17
        
        -	data, err := os.ReadFile(path)

      
        
        16
        +	data, err := os.ReadFile(filepath.Join("testdata", path+".input"))

      
        18
        17
         	if err != nil {

      
        19
        
        -		t.Fatalf("reading input file %s: %v", path, err)

      
        
        18
        +		t.Fatalf("loading %s: %v", path, err)

      
        20
        19
         	}

      
        21
        20
         	return data

      
        22
        21
         }

      
        23
        22
         

      
        24
        
        -func AssertInput(t testing.TB, got string, name string) {

      
        
        23
        +// Assert compares got against testdata/<name>.golden.

      
        
        24
        +func Assert(t testing.TB, name, got string) {

      
        25
        25
         	t.Helper()

      
        26
        26
         

      
        27
        
        -	path := filepath.Join("testdata", name+".golden")

      
        
        27
        +	normalized := strings.NewReplacer("/", "__", " ", "_").Replace(name)

      
        
        28
        +	path := filepath.Join("testdata", normalized+".golden")

      
        
        29
        +

      
        28
        30
         	if *update {

      
        29
        31
         		if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {

      
        30
        32
         			t.Fatalf("creating testdata dir: %v", err)

      ···
        47
        49
         		t.Fatalf("golden mismatch for %s\nwant:\n%s\ngot:\n%s", path, string(golden), got)

      
        48
        50
         	}

      
        49
        51
         }

      
        50
        
        -

      
        51
        
        -func Assert(t testing.TB, got string) {

      
        52
        
        -	t.Helper()

      
        53
        
        -

      
        54
        
        -	name := strings.NewReplacer("/", "__", " ", "_").Replace(t.Name())

      
        55
        
        -	name = strings.TrimPrefix(name, "Test")

      
        56
        
        -	path := filepath.Join("testdata", "golden", name+".golden")

      
        57
        
        -

      
        58
        
        -	if *update {

      
        59
        
        -		if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {

      
        60
        
        -			t.Fatalf("creating golden dir: %v", err)

      
        61
        
        -		}

      
        62
        
        -		t.Logf("updated golden file: %s", path)

      
        63
        
        -		if err := os.WriteFile(path, []byte(got), 0o644); err != nil {

      
        64
        
        -			t.Fatalf("writing golden file: %v", err)

      
        65
        
        -		}

      
        66
        
        -		return

      
        67
        
        -	}

      
        68
        
        -

      
        69
        
        -	golden, err := os.ReadFile(path)

      
        70
        
        -	if os.IsNotExist(err) {

      
        71
        
        -		t.Fatalf("no golden file %s, run with -golden.update:\n%s", path, got)

      
        72
        
        -	}

      
        73
        
        -	if err != nil {

      
        74
        
        -		t.Fatalf("reading golden file: %v", err)

      
        75
        
        -	}

      
        76
        
        -

      
        77
        
        -	if string(golden) != got {

      
        78
        
        -		t.Fatalf("golden mismatch for %s\nwant:\n%s\ngot:\n%s", path, string(golden), got)

      
        79
        
        -	}

      
        80
        
        -}

      
M journal/lexer/lexer_test.go
···
        84
        84
         	for _, tt := range tests {

      
        85
        85
         		t.Run(tt.name, func(t *testing.T) {

      
        86
        86
         			l := New("j", []byte(tt.input))

      
        87
        
        -			golden.Assert(t, l.Dump())

      
        
        87
        +			golden.Assert(t, tt.name, l.Dump())

      
        88
        88
         		})

      
        89
        89
         	}

      
        90
        90
         }

      
M journal/parser/parser_test.go
···
        322
        322
         		t.Run(tt.name, func(t *testing.T) {

      
        323
        323
         			l := lexer.New("j", []byte(tt.inp))

      
        324
        324
         			f := New(l).ParseJournal()

      
        325
        
        -			golden.Assert(t, ast.Dump(f))

      
        
        325
        +			golden.Assert(t, tt.name, ast.Dump(f))

      
        326
        326
         		})

      
        327
        327
         	}

      
        328
        328
         }

      
M journal/printer/printer_test.go
···
        24
        24
         				t.Fatal(err)

      
        25
        25
         			}

      
        26
        26
         

      
        27
        
        -			golden.AssertInput(t, b.String(), tname)

      
        
        27
        +			golden.Assert(t, tname, b.String())

      
        28
        28
         		})

      
        29
        29
         	}

      
        30
        30
         }

      ···
        71
        71
         				t.Fatal(err)

      
        72
        72
         			}

      
        73
        73
         

      
        74
        
        -			golden.AssertInput(t, b.String(), tname)

      
        
        74
        +			golden.Assert(t, tname, b.String())

      
        75
        75
         		})

      
        76
        76
         	}

      
        77
        77
         }

      
M journal/tags/tag_test.go
···
        16
        16
         		t.Run(tt, func(t *testing.T) {

      
        17
        17
         			inp := golden.Load(t, tt)

      
        18
        18
         			out := generateTags(t, inp, tt+".journal")

      
        19
        
        -			golden.AssertInput(t, out, tt)

      
        
        19
        +			golden.Assert(t, tt, out)

      
        20
        20
         		})

      
        21
        21
         	}

      
        22
        22
         }

      ···
        41
        41
         		t.Fatal(err)

      
        42
        42
         	}

      
        43
        43
         

      
        44
        
        -	golden.AssertInput(t, buf.String(), "crossfile")

      
        
        44
        +	golden.Assert(t, "crossfile", buf.String())

      
        45
        45
         }

      
        46
        46
         

      
        47
        47
         func generateTags(t *testing.T, src []byte, fname string) string {