testable(docs) gloo-foo manual

Name

testablePublic documentation for the project.

The shared test harness for gloo-foo pipeline commands. It runs a Command[[]byte, []byte] against in-memory input and returns the captured output, so a command can be exercised without touching real files or I/O — behaving identically under test and in production.

Install

sh
go get github.com/gloo-foo/testable

Usage

Test and TestLines are the convenience entry points used by the cmd-* modules. They run a command against a string of input and capture its stdout. Test returns the output as a single string (each line terminated by \n); TestLines returns it as a slice of lines. Both propagate a command failure as the returned error (with an empty string / nil slice, respectively).

go
import (
	gloo "github.com/gloo-foo/framework"
	"github.com/gloo-foo/framework/patterns"

	"github.com/gloo-foo/testable"
)

// upper stands in for a real cmd-* command: it upper-cases each input line.
func upper() gloo.Command[[]byte, []byte] {
	return patterns.Map(func(line []byte) ([]byte, error) {
		return []byte(strings.ToUpper(string(line))), nil
	})
}

lines, err := testable.TestLines(upper(), "hello\nworld\n")
// err   == nil
// lines == []string{"HELLO", "WORLD"}

out, err := testable.Test(upper(), "hello\nworld\n")
// out == "HELLO\nWORLD\n"

Design

The top-level helpers delegate to gloo-foo/fn — the production adapter that runs a command as an ordinary data function — so a command’s behavior under test matches its behavior in use. Three subpackages cover finer-grained needs:

run — fluent runner

run gives explicit control over a command’s input: a custom reader, injected read errors, or an explicit context. Every With* method returns a new Runner, so a Runner is immutable and safe to reuse. Run is the terminal operation, returning a *Result with Stdout []string and Err error.

go
import "github.com/gloo-foo/testable/run"

res := run.Command(upper()).WithStdinLines("alpha", "beta").Run()
// res.Stdout == []string{"ALPHA", "BETA"}
// res.Err    == nil

Runner constructors: Command (empty stdin, background context) and WithContext. Input configuration: WithStdin, WithStdinLines, WithStdinReader, WithStdinError (fail the input stream to exercise error propagation), and WithContext. Shorthands: Quick(cmd) runs with empty stdin; WithInput(cmd, stdin) runs with a given input string.

splitter — field splitting

splitter supplies FieldFunc strategies for breaking a line into fields:

  • Whitespace — splits on runs of whitespace when the separator is " ", otherwise on the exact separator string (mimics awk’s default field splitting).
  • Exact — always splits on the exact separator, treating " " as a literal space.
  • Fixed(positions...) — splits at 0-based fixed-width column positions; the last field extends to the end of the line.
  • CharacterClass — splits on any character contained in the separator string (like a regex character class).
  • Pattern(splitFunc) — wraps an arbitrary func(string) []string as a FieldFunc.
go
import "github.com/gloo-foo/testable/splitter"

splitter.Whitespace("a  b   c", " ")     // [a b c]
splitter.Exact("a,b,,c", ",")            // [a b  c]
splitter.Fixed(0, 3, 6)("abcdefghij", "") // [abc def ghij]
splitter.CharacterClass("a,b;c:d", ",;:") // [a b c d]

assertion — output assertions

assertion provides assertion helpers for command output, each taking a reporter (satisfied by *testing.T) as its first argument: Lines, Contains, NotContains, Empty, Count, Prefix, Suffix, ErrorContains, NoError, Error, Equal (generic over comparable), True, False, and the Format message helper. Failures are reported through Errorf with detailed, line-by-line diffs.