Groups failed tests by similar error messages.
Provides functionality for the --group-by-error option, which helps
identify patterns in test failures by grouping them by error message.
Summary
Functions
Groups failed tests by similar error message (first line of first failure).
Extracts the grouping key from a failed test.
Truncates long patterns to a reasonable length for display.
Types
@type encoded_test() :: map()
A JSON-encoded test result map
@type error_group() :: %{ pattern: String.t(), count: non_neg_integer(), example: %{ name: String.t(), module: String.t(), file: String.t(), line: non_neg_integer() } }
An error group with pattern, count, and example test
Functions
@spec build_error_groups([encoded_test()]) :: [error_group()]
Groups failed tests by similar error message (first line of first failure).
Returns list of groups sorted by count descending.
Examples
failed_tests = [
%{name: "t1", failures: [%{message: "timeout"}], ...},
%{name: "t2", failures: [%{message: "timeout"}], ...},
%{name: "t3", failures: [%{message: "connection refused"}], ...}
]
build_error_groups(failed_tests)
#=> [
#=> %{pattern: "timeout", count: 2, example: %{...}},
#=> %{pattern: "connection refused", count: 1, example: %{...}}
#=> ]
@spec extract_error_pattern(encoded_test()) :: String.t()
Extracts the grouping key from a failed test.
Uses the first line of the first failure message as the pattern. Normalizes whitespace for better grouping of similar errors.
Examples
test = %{failures: [%{message: "timeout after 30s\ndetails here"}]}
extract_error_pattern(test)
#=> "timeout after 30s"
test_no_failures = %{failures: []}
extract_error_pattern(test_no_failures)
#=> "(unknown error)"
Truncates long patterns to a reasonable length for display.
Adds "..." suffix when truncated.
Examples
truncate_pattern("short")
#=> "short"
truncate_pattern(String.duplicate("x", 300))
#=> "xxx...xxx..." # 200 chars + "..."