john1234
john1234

Reputation: 225

How to test "main()" routine from "go test"?

I want to lock the user-facing command line API of my golang program by writing few anti-regression tests that would focus on testing my binary as a whole. What testing "binary as a whole" means is that go-test should:

  1. be able to feed STDIN to my binary
  2. be able to check that my binary produces correct STDOUT
  3. be able to ensure that error cases are handled properly by binary

However, it is not obvious to me what is the best practice to do that in go? If there is a good go test example, could you point me to it?

P.S. in the past I have been using autotools. And I am looking for something similar to AT_CHECK, for example:

AT_CHECK([echo "XXX" | my_binary -e arg1 -f arg2], [1], [],
  [-f and -e can't be used together])

Upvotes: 6

Views: 8851

Answers (3)

davecb
davecb

Reputation: 304

I think you're trying too hard: I just tried the following

func TestMainProgram(t *testing.T) {
    os.Args = []string{"sherlock",
        "--debug", 
        "--add", "zero",
        "--ruleset", "../scripts/ceph-log-filters/ceph.rules",
        "../scripts/ceph-log-filters/ceph.log"}
    main()
}

and it worked fine. I can make a normal tabular test or a goConvey BDD from it pretty easily...

Upvotes: 8

dmitris
dmitris

Reputation: 1491

If you really want to do such type of testing in Go, you can use Go os/exec package https://golang.org/pkg/os/exec/ to execute your binary and test it as a whole - for example, executing go run main.go command. Essentially it would be an equivalent of a shell script done in Go. You can use StdinPipe https://golang.org/pkg/os/exec/#Cmd.StdinPipe and StdouPipe/StderrPipe (https://golang.org/pkg/os/exec/#Cmd.StdoutPipe and https://golang.org/pkg/os/exec/#Cmd.StderrPipe) to feed the desired input and verify output. The examples on the package documentation page https://golang.org/pkg/os/exec/ should give you a good starting point.

However, the testing of compiled programs goes beyond the unit testing so it is worth to consider other tools (not necessarily Go-based) that more typically used for functional / acceptance testing such as Cucumber http://cucumber.io.

Upvotes: 1

Sławosz
Sławosz

Reputation: 11687

Just make your main() single line:

import "myapp"

func main() {
    myapp.Start()
}

And test myapp package properly.

EDIT: For example, popular etcd conf server uses this technique: https://github.com/coreos/etcd/blob/master/main.go

Upvotes: 6

Related Questions