From bd8de43ad9293c712025cf79c9e10ca82346b7c0 Mon Sep 17 00:00:00 2001 From: t_ Date: Sun, 19 Feb 2017 06:39:39 +0900 Subject: [PATCH] improve testability --- .travis.yml | 2 +- cmd/gocha/cli.go | 53 +++++++++++++++++++++++++++++++ cmd/gocha/cli_test.go | 73 +++++++++++++++++++++++++++++++++++++++++++ cmd/gocha/main.go | 43 +------------------------ 4 files changed, 128 insertions(+), 43 deletions(-) create mode 100644 cmd/gocha/cli.go create mode 100644 cmd/gocha/cli_test.go diff --git a/.travis.yml b/.travis.yml index 7f2e974..10080f1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: go script: - - go test -v + - go test -cover -v . ./cmd/gocha - go test -bench . diff --git a/cmd/gocha/cli.go b/cmd/gocha/cli.go new file mode 100644 index 0000000..0d6f318 --- /dev/null +++ b/cmd/gocha/cli.go @@ -0,0 +1,53 @@ +package main + +import ( + "fmt" + "io" + + "github.com/t-mrt/gocha" + "gopkg.in/alecthomas/kingpin.v2" +) + +const ( + ExitCodeOK = iota + ExitCodeError +) + +type CLI struct { + outStream io.Writer + errStream io.Writer +} + +func (c *CLI) Run(args []string) int { + var app = kingpin.New("gocha", "Random strings generater based on a pattern.") + + var pattern = app.Arg("pattern", "Regular expression").Required().String() + var num = app.Flag("number-of-lines", "Number of lines").Short('n').Int() + + var exitCode int + kingpin.CommandLine.Writer(c.errStream).Terminate(func(i int) { + exitCode = i + }) + kingpin.MustParse(app.Parse(args[1:])) + + if exitCode == ExitCodeError { + return ExitCodeError + } + + err, g := gocha.New(*pattern) + + if err != nil { + fmt.Fprintf(c.errStream, "gocha: %v\n", err.Error()) + return ExitCodeError + } + + if *num <= 0 { + *num = 1 + } + + for i := 0; i < *num; i++ { + fmt.Fprintln(c.outStream, g.Gen()) + } + + return ExitCodeOK +} diff --git a/cmd/gocha/cli_test.go b/cmd/gocha/cli_test.go new file mode 100644 index 0000000..a62b444 --- /dev/null +++ b/cmd/gocha/cli_test.go @@ -0,0 +1,73 @@ +package main + +import ( + "bytes" + "fmt" + "strings" + "testing" +) + +func TestRun(t *testing.T) { + t.Run("ExitCodeOK", func(t *testing.T) { + outStream, errStream := new(bytes.Buffer), new(bytes.Buffer) + cli := &CLI{outStream: outStream, errStream: errStream} + args := strings.Split("gocha -n 1 '[a]{3}'", " ") + status := cli.Run(args) + + if status != ExitCodeOK { + t.Errorf("ExitStatus=%d, want %d", status, ExitCodeOK) + } + + expected := fmt.Sprintf("") + if errStream.String() != expected { + t.Errorf("Output=%q, want %q", errStream.String(), expected) + } + + expected = fmt.Sprintf("'aaa'\n") + if outStream.String() != expected { + t.Errorf("Output=%q, want %q", outStream.String(), expected) + } + }) + + t.Run("ExitCodeError", func(t *testing.T) { + outStream, errStream := new(bytes.Buffer), new(bytes.Buffer) + cli := &CLI{outStream: outStream, errStream: errStream} + args := strings.Split("gocha -n 1 '.{100000}'", " ") + status := cli.Run(args) + + if status != ExitCodeError { + t.Errorf("ExitStatus=%d, want %d", status, ExitCodeOK) + } + + expected := fmt.Sprintf("gocha: error parsing regexp: invalid repeat count: `{100000}`\n") + if errStream.String() != expected { + t.Errorf("Output=%q, want %q", errStream.String(), expected) + } + + expected = fmt.Sprintf("") + if outStream.String() != expected { + t.Errorf("Output=%q, want %q", outStream.String(), expected) + } + }) + + t.Run("RequirePattern", func(t *testing.T) { + outStream, errStream := new(bytes.Buffer), new(bytes.Buffer) + cli := &CLI{outStream: outStream, errStream: errStream} + args := strings.Split("gocha -n 1", " ") + status := cli.Run(args) + + if status != ExitCodeError { + t.Errorf("ExitStatus=%d, want %d", status, ExitCodeError) + } + + expected := fmt.Sprintf("gocha.test: error: required argument 'pattern' not provided, try --help\n") + if errStream.String() != expected { + t.Errorf("Output=%q, want %q", errStream.String(), expected) + } + + expected = fmt.Sprintf("") + if outStream.String() != expected { + t.Errorf("Output=%q, want %q", outStream.String(), expected) + } + }) +} diff --git a/cmd/gocha/main.go b/cmd/gocha/main.go index 5550cd5..9c033c1 100644 --- a/cmd/gocha/main.go +++ b/cmd/gocha/main.go @@ -1,47 +1,6 @@ package main -import ( - "fmt" - "io" - "os" - - "github.com/t-mrt/gocha" - "gopkg.in/alecthomas/kingpin.v2" -) - -const ( - ExitCodeOK = iota - ExitCodeError -) - -type CLI struct { - outStream io.Writer - errStream io.Writer -} - -func (c *CLI) Run(args []string) int { - - var pattern = kingpin.Arg("pattern", "Regular expression").Required().String() - var num = kingpin.Flag("number-of-lines", "Number of lines").Short('n').Int() - kingpin.Parse() - - err, g := gocha.New(*pattern) - - if err != nil { - fmt.Fprintln(c.outStream, "gocha: error: Invalid regular expression") - return ExitCodeError - } - - if *num <= 0 { - *num = 1 - } - - for i := 0; i < *num; i++ { - fmt.Fprintln(c.outStream, g.Gen()) - } - - return ExitCodeOK -} +import "os" func main() { cli := &CLI{outStream: os.Stdout, errStream: os.Stderr}