Cobraを使用してCLIアプリケーションを作成する
サンプルコード
main.go
package main
import (
"os"
"strings"
"github.com/spf13/cobra"
)
func NewRootCommand() *cobra.Command {
cmd := &cobra.Command{
Run: func(cmd *cobra.Command, args []string) {
cmd.Help()
},
}
return cmd
}
func NewSubCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "sub",
Run: func(cmd *cobra.Command, args []string) {
cmd.Println("Print: " + strings.Join(args, " "))
},
}
return cmd
}
func main() {
cmd := NewRootCommand()
cmd.AddCommand(
NewSubCommand(),
)
if err := cmd.Execute(); err != nil {
cmd.Print(err)
os.Exit(1)
}
}
- cobraのサンプルコードでは変数に
*cobra.Command
を保存する方式を採っているが、あれでは外部からモジュールをインジェクションできないのでよくない
- コマンド毎に
*cobra.Command
を返す関数を作って、引数でモジュールをインジェクションできるようにするのが望ましい(サンプルコードではやっていない)
テストコード
func TestRootCommand(t *testing.T) {
tests := []struct {
name string
result string
}{
{
name: "正常系",
result: "TEST",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
stdio := new(bytes.Buffer)
cmd := NewRootCommand()
cmd.SetOut(stdio)
cmd.SetErr(stdio)
cmd.Execute()
t.Log(stdio.String())
t.Log(test.result)
})
}
}
- 標準入出力を
bytes.Buffer
に置き換えて、実行後に出力を検証できるようにしている
- 実行ログを垂れ流すようにしているとテストが困難になるので、ロガーを弄って何も出力しないようにしている
- 実行ログの出力は結合試験で確認できればよいという考え方
参考資料