Skip to content

veggiemonk/testscript

Repository files navigation

testscript

A Go library for filesystem-based test scripting.

What is testscript?

testscript lets you test CLI tools by writing scripts in a simple, shell-like language. Scripts live alongside your Go tests in txtar files. Each script runs commands, checks output, and manages files -- all without writing Go boilerplate for every test case.

Quickstart

Create a trivial CLI, a test harness, and a test script.

main.go

package main

import (
	"flag"
	"fmt"
	"os"
)

func main() {
	name := flag.String("name", "", "name to greet")
	flag.Parse()
	if *name == "" {
		fmt.Fprintln(os.Stderr, "usage: hello --name <name>")
		os.Exit(1)
	}
	fmt.Printf("Hello, %s!\n", *name)
}

main_test.go

package main_test

import (
	"testing"

	"github.com/veggiemonk/testscript/scripttest"
)

func TestMain(m *testing.M) {
	scripttest.Main(m, map[string]func(){
		"hello": main,
	})
}

func TestScripts(t *testing.T) {
	scripttest.Test(t, "testdata/*.txt")
}

testdata/hello.txt

# success case
exec hello --name World
stdout 'Hello, World!'

# error case: missing --name flag
! exec hello
stderr 'usage: hello --name <name>'

Run:

go test -v

How it works

Test scripts use the txtar format. The comment section (before any file entries) is the script itself. File entries below the -- markers become files in the test's working directory.

The engine parses and executes the script line by line. Each line is a command with optional condition guards and prefix modifiers (! for expected failure, ? for don't-care). Lines starting with # are section comments that appear in the test log with elapsed time.

scripttest.Main compiles your CLI functions into executables available on $PATH during test execution. scripttest.Test creates a parallel subtest for each matched txtar file.

Built-in commands

Command Description
cat Concatenate files and print to stdout buffer
cd Change the working directory
chmod Change file mode bits (numerical permissions only)
cmp Compare two files (or stdout/stderr with a file) for differences
cmpenv Compare files with environment variable expansion
cp Copy files to a target file or directory
echo Display a line of text
env Set or print environment variables
exec Run an executable program with arguments
exists Check that files exist (with optional -readonly, -exec flags)
grep Find lines in a file matching a Go regexp
help Log help text for commands and conditions
mkdir Create directories (parents created automatically)
mv Rename a file or directory
replace Replace strings in a file (old/new pairs, Go string unquoting)
rm Remove a file or directory recursively
sleep Sleep for a specified duration (Go duration string)
stderr Match a Go regexp against the stderr buffer
stdin Set standard input for the next exec command
stdout Match a Go regexp against the stdout buffer
stop Stop script execution (success)
symlink Create a symbolic link (path -> target)
unquote Remove txtar > quoting from a file in place
wait Wait for background commands to complete
skip Skip the current test (from scripttest)
update Update a golden file in the txtar archive with current stdout (from scripttest)

Use -testscript.update flag to automatically update golden files:

go test -testscript.update

Built-in conditions

Condition Description
[GOOS:os] True when runtime.GOOS matches (e.g. [GOOS:linux])
[GOARCH:arch] True when runtime.GOARCH matches (e.g. [GOARCH:amd64])
[exec:prog] True when prog is found in the test binary's PATH
[short] True when go test -short is set
[verbose] True when go test -v is set
[root] True when running as root (euid == 0)
[!cond] Negate any condition (e.g. [!GOOS:windows])

Tutorials

Credits

Derived from rsc.io/script and github.com/rogpeppe/go-internal/testscript.

Recommended reading:

License

BSD 3-Clause. See LICENSE.

About

library for filesystem-based test scripting. Derived from rsc.io/script and github.com/rogpeppe/go-internal/testscript.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages