Testing
When testing cobra commands, you want to try and decouple your core logic into
libraries, similar to what we did with the sum
and subtract
functions for
their respective commands.
This makes testing a bit easier in that you don't need to wrap a bunch of
cobra.Command
context into your unit tests.
With that said, you may find yourself needing to test calling your cobra command to get more coverage. In that case, I would recommend borrowing a testing function from the cobra library itself.
https://github.com/spf13/cobra/blob/main/command_test.go#L34-L43
func executeCommandC(root *Command, args ...string) (c *Command, output string, err error) {
buf := new(bytes.Buffer)
root.SetOut(buf)
root.SetErr(buf)
root.SetArgs(args)
c, err = root.ExecuteC()
return c, buf.String(), err
}
This function calls your commands and returns your stdout/stderr streams (together, but you can modify this to separate them if you need to), and an error if your command returned one. It also returns your command should you need it.
So executing this for the subtract command would look something like this:
func TestSubtractCmd(t *testing.T) {
_, _, err := executeCommandC(rootCmd, "arithmetic", "subtract", "1", "2")
if err != nil {
t.Log(err)
t.Fail()
}
}
Here, we pass rootCmd
as our command to execute. We could also pass
subtractCmd
, and then just pass "1"
and "2"
as parameters, but showing it
this way might help in understanding all the various ways you can leverage
executeCommandC
to run your tests.
NOTE: Remember earlier that we wrote our execution output to the
cmd.OutOrStdout
target. This is important here because we can actually
evaluate the output of our command execution. If we had used fmt.Println
instead, we would have a harder time trying to capture the command output stream
to evaluate for any failures.