Testing the edges of a system reveals which paths can actually occur. If you can't test it, can it really happen?
This example shows how to design func main so it can be fully tested
with go test. Move logic into func run and handle fatal errors
in func end.
func main() {
verbose := flag.Bool("verbose", false, "")
flag.Usage = usage(os.Stderr, os.Args[0])
flag.Parse()
err := run(os.Stdout, *verbose)
end(err, os.Stderr, os.Exit)
}
func usage(w io.Writer, name string) func() {
return func() {
tpl := `%s: [OPTIONS]
Options
`
fmt.Fprintf(w, tpl, name)
flag.CommandLine.SetOutput(w)
flag.PrintDefaults()
}
}
// end writes out error and calls exit if error is not nil.
func end(err error, stderr io.Writer, exit func(int)) {
if err != nil {
fmt.Fprintln(stderr, err)
exit(1)
}
}
// ---- put func run in run.go ----
func run(stdout io.Writer, verbose bool) error {
if verbose {
fmt.Fprint(stdout, "hello world")
}
return nil
}
func Test_main(t *testing.T) {
os.Args = []string{"", "-verbose"}
main()
}
func Test_usage(t *testing.T) {
var buf bytes.Buffer
usage(&buf, "")()
got := buf.String()
if !strings.Contains(got, "-verbose") {
t.Error(got)
}
}
func Test_end(t *testing.T) {
var code *int
catchExitCode := func(v int) { code = &v }
end(io.EOF, io.Discard, catchExitCode)
if code == nil {
t.Fatal("func exit not called")
}
if *code != 1 {
t.Errorf("%v: not 1", code)
}
}