Name
testable — Public 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.
- Source: gloo-foo/testable
- API reference: pkg.go.dev/github.com/gloo-foo/testable
Install
go get github.com/gloo-foo/testableUsage
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).
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.
import "github.com/gloo-foo/testable/run"
res := run.Command(upper()).WithStdinLines("alpha", "beta").Run()
// res.Stdout == []string{"ALPHA", "BETA"}
// res.Err == nilRunner 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 arbitraryfunc(string) []stringas aFieldFunc.
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.