Go TestScript #
概要 #
- TestScript は元々 Go のコンパイラをテストするために作成されたもの。
https://cs.opensource.google/go/go/+/release-branch.go1.19:src/cmd/go/script_test.go - シェルスクリプトのように記述でき、ファイルシステム上で動作するものをテストできる。
- 定義済のコマンドは以下で確認できる。
https://cs.opensource.google/go/go/+/release-branch.go1.19:src/cmd/go/script_test.go - 独自のコマンドを追加することができる。
- Go のコンパイル時に使用される TestScript は以下で確認できる。
https://cs.opensource.google/go/go/+/master:src/cmd/go/testdata/script/ - TestScript は txtar (テキストベースのアーカイブ形式) によって表現されている。
https://pkg.go.dev/golang.org/x/tools/txtar - Go 内部のテストコードを使用できるよう、再構成されたものが以下で公開されている。
https://github.com/rogpeppe/go-internal/tree/master/testscript
テストコードの書き方 #
定義済コマンドをテストで使用 #
testdata/script/TestFoo/hello-world.txt
exec echo 'hello world!'
stdout 'hello world!\n'
sample_test.go
package sample_test
import (
"path/filepath"
"testing"
"github.com/rogpeppe/go-internal/testscript"
)
var scriptDir = filepath.Join("testdata", "script")
func TestFoo(t *testing.T) {
t.Parallel()
testscript.Run(t, testscript.Params{
Dir: filepath.Join(scriptDir, t.Name()),
WorkdirRoot: t.TempDir(),
})
}
独自のコマンドを作成してテストで使用 #
testdata/script/TestFoo/hello-world.txt
mycat hello.txt world.txt
stdout 'hello\n'
stdout 'world!\n'
-- hello.txt --
hello
-- world.txt --
world!
sample_test.go
package sample_test
import (
"os"
"path/filepath"
"testing"
"github.com/rogpeppe/go-internal/testscript"
)
var scriptDir = filepath.Join("testdata", "script")
func TestMain(m *testing.M) {
os.Exit(testscript.RunMain(m, map[string]func() int{
"mycat": mycat,
}))
}
func TestFoo(t *testing.T) {
t.Parallel()
testscript.Run(t, testscript.Params{
Dir: filepath.Join(scriptDir, t.Name()),
WorkdirRoot: t.TempDir(),
})
}
// mycat behaves like cat command.
// Do NOT use *testing.T as an argument because we use mycat in testscript.RunMain().
func mycat() int {
if len(os.Args) == 1 {
_, err := io.Copy(os.Stdout, os.Stdin)
if err != nil {
return 1
}
return 0
}
for _, fname := range os.Args[1:] {
f, err := os.Open(fname)
if err != nil {
return 1
}
_, err = io.Copy(os.Stdout, f)
if err != nil {
return 1
}
}
return 0
}