Documentation ¶
Overview ¶
Package exectest provides helpers for test code that wants to mock out pieces of the os/exec package, namely exec.Command(). For explanations see: https://web.archive.org/web/20220506055022/https://npf.io/2015/06/testing-exec-command/ https://web.archive.org/web/20220506055117/https://jamiethompson.me/posts/Unit-Testing-Exec-Command-In-Golang/
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func RegisterMains ¶
func RegisterMains(m ...Main)
RegisterMains makes multiple Main functions available to Run in the test subprocess. Call it only from your test package's init functions. Any Main functions passed to NewCommand must be registered using this function.
func Run ¶
Run is a wrapper for testing.M.Run() to use in conjunction with RegisterMains() and NewCommand().
During the first run of the test executable, it simply calls m.Run() and returns its exit code. When the test executable is reinvoked by a Command implementation, it uses the information contained in os.Args[0] to execute a Main function instead. In that case, Run will not return.
Types ¶
type Command ¶
Command is a function that has an identical signature to exec.Command(). It is created with a call to NewCommand().
func NewCommand ¶
NewCommand returns a drop-in replacement for os/exec.Command. The exec.Cmd that the Command returns will invoke the passed Main function in a new test subprocess. The original arguments passed to the returned Command will be passed to the subprocess.
The intended use case is for test packages to replace exec.Command in the packages they are testing with the resulting Command created by this function.
To use NewCommand, two pieces of test boilerplate are required. The first is that any Main functions must be explicitly declared to the exectest package by calling RegisterMains from the test package's init function:
func MyExecutable() { os.Exit(1) } func init() { exectest.RegisterMains( MyExecutable, ) }
The second is that the test suite must be started using exectest.Run:
func TestMain(m *testing.M) { os.Exit(exectest.Run(m)) }
Once these conditions are met, the function handed back from NewCommand may be used exactly like you would use exec.Command():
execCommand := exectest.NewCommand(MyExecutable) cmd := execCommand("/bin/bash", "-c", "sleep 15") cmd.Run() // this invokes MyExecutable, not Bash
func NewCommandWithVerifier ¶
NewCommandWithVerifier works like NewCommand, with an additional verifier callback that is run against the supplied arguments. This allows unit tests to explicitly check the arguments that are passed to exec.Command():
execCommand := exectest.NewCommandWithVerifier(MyExecutable, func(name string, arg ...string)) { if name != "/bin/bash" { t.Errorf("didn't use Bash") } } ) execCommand("/bin/bash", "-c", "sleep 1") // succeeds execCommand("/bin/sh", "-c", "sleep 1") // logs a test failure