be: Minimal Go Testing Assertions

repository·main·Indexed 42 days ago

https://github.com/nalgeon/be

A minimal, opinionated Go testing assertion package providing a streamlined API with three core functions: Equal, Err, and True. It offers flexible error assertions via be.Err, smart value comparison in be.Equal, and boolean checks with be.True, serving as a lightweight alternative to libraries like testify.

Tokens
1.3K
Snippets
8
Records
9
Agent score
3%

What's inside be

  1. Understand the design philosophy of be

    main

    The be package is designed to be a minimal, opinionated alternative to testify or is. Key design principles include:

    • Minimal API: Only three functions: Equal, Err, and True.
    • No Custom Messages: The package does not support custom error messages for assertions; it relies on the test runner's line numbers to identify failures.
    • Non-terminating Failures: Most assertions do not stop the test execution immediately, allowing you to see multiple failures at once. The only exception is be.Err(t, err, nil) failing (when an unexpected error occurs), which terminates the test to prevent subsequent panics.
    • Natural Parameter Order: Uses (got, want) rather than (want, got) to follow natural language patterns (e.g., "balance is 100").
    • Flexible Error Handling: A single Err function replaces the need for ErrorIs, ErrorAs, NoError, etc.
  2. Use Equal for value assertions

    main

    The Equal function asserts that a value matches a specific value or any of a set of provided values. It uses an Equal method for comparison, which correctly handles time.Time and other types that implement it. Note that the parameter order is (t, got, want).

    // Assert equality between two values
    be.Equal(t, "hello", "hello")
    
    // Assert that a value matches any of the provided values
    be.Equal(t, 42, 21, 42, 84)
  3. Use Err for flexible error assertions

    main

    The Err function is a multi-purpose assertion for errors. Instead of having separate functions for different error checks, be.Err handles existence, value matching, substring matching, and type checking in a single interface.

    Supported patterns:

    • be.Err(t, err): Asserts that err is not nil.
    • be.Err(t, err, nil): Asserts that err is nil (no error).
    • be.Err(t, err, "substring"): Asserts that the error message contains the substring.
    • be.Err(t, err, targetErr): Asserts that err matches targetErr via errors.Is.
    • be.Err(t, err, reflect.TypeFor[T]()): Asserts that the error matches type T via errors.As.
    • be.Err(t, err, ...args): A mix of the above can be passed as multiple arguments.
    // Assert error exists
    be.Err(t, err)
    
    // Assert no error exists
    be.Err(t, err, nil)
    
    // Assert error message contains substring
    be.Err(t, err, "invalid or unsupported")
    
    // Assert error matches via errors.Is
    be.Err(t, err, fs.ErrNotExist)
    
    // Assert error type matches via errors.As
    be.Err(t, err, reflect.TypeFor[*fs.PathError]())
    
    // Mix multiple assertions
    be.Err(t, err, "failed", AppError("oops"), reflect.TypeFor[AppError]())
  4. Quickstart: Example usage of be assertions

    main

    This example demonstrates how to use the three core assertion functions (Err, True, and Equal) in a standard Go test.

    func Test(t *testing.T) {
    	re, err := regexp.Compile("he??o")
    	be.Err(t, err, nil) // expects no error
    	be.True(t, strings.Contains(re.String(), "?"))
    	be.Equal(t, re.String(), "he??o")
    }
  5. Use Err() to assert error conditions

    main

    The Err function asserts that the got error matches any of the provided wants. The matching logic varies based on the type of want provided:

    • nil: Checks if got is nil.
    • string: Checks if got.Error() contains the string.
    • error: Uses errors.Is to check if the error is found in the error tree.
    • reflect.Type: Uses errors.As to check if the error can be assigned to the specified type.
    • No arguments: If no wants are provided, it asserts that got is not nil.

    If want is nil and got is not nil, the test fails fatally via tb.Fatalf.

    // expects no error
    be.Err(t, err, nil) 
  6. Use Equal() to assert equality

    main

    The Equal function asserts that the got value matches any of the provided wants values. It uses a smart comparison logic: it first checks if the type implements an Equal(T) bool method (like time.Time), then checks specifically for []byte equality, and finally falls back to reflect.DeepEqual. If no wants are provided, the test fails fatally.

    be.Equal(t, re.String(), "he??o")
  7. Use True() to assert boolean truth

    main

    The True function asserts that the got boolean value is true. If got is false, it reports a failure using tb.Error.

    be.True(t, strings.Contains(re.String(), "?"))