diff --git a/cmd/run.go b/cmd/run.go index a72a96f69..6f3a75b83 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -3,6 +3,7 @@ package cmd import ( "context" "fmt" + "io" "os" "path" "path/filepath" @@ -30,6 +31,7 @@ type runOption struct { limiter limit.RateLimiter startTime time.Time reporter runner.TestReporter + reportFile string reportWriter runner.ReportResultWriter report string reportIgnore bool @@ -72,17 +74,27 @@ See also https://github.com/LinuxSuRen/api-testing/tree/master/sample`, flags.DurationVarP(&opt.duration, "duration", "", 0, "Running duration") flags.DurationVarP(&opt.requestTimeout, "request-timeout", "", time.Minute, "Timeout for per request") flags.BoolVarP(&opt.requestIgnoreError, "request-ignore-error", "", false, "Indicate if ignore the request error") + flags.StringVarP(&opt.report, "report", "", "", "The type of target report. Supported: markdown, md, discard, std") + flags.StringVarP(&opt.reportFile, "report-file", "", "", "The file path of the report") flags.BoolVarP(&opt.reportIgnore, "report-ignore", "", false, "Indicate if ignore the report output") flags.Int64VarP(&opt.thread, "thread", "", 1, "Threads of the execution") flags.Int32VarP(&opt.qps, "qps", "", 5, "QPS") flags.Int32VarP(&opt.burst, "burst", "", 5, "burst") - flags.StringVarP(&opt.report, "report", "", "", "The type of target report. Supported: markdown, md, discard, std") return } func (o *runOption) preRunE(cmd *cobra.Command, args []string) (err error) { writer := cmd.OutOrStdout() + if o.reportFile != "" { + var reportFile *os.File + if reportFile, err = os.Create(o.reportFile); err != nil { + return + } + + writer = io.MultiWriter(writer, reportFile) + } + switch o.report { case "markdown", "md": o.reportWriter = runner.NewMarkdownResultWriter(writer) diff --git a/cmd/run_test.go b/cmd/run_test.go index 32a269773..f82f9e7b1 100644 --- a/cmd/run_test.go +++ b/cmd/run_test.go @@ -5,6 +5,8 @@ import ( "context" "errors" "net/http" + "os" + "path" "testing" "time" @@ -66,6 +68,13 @@ func TestRunCommand(t *testing.T) { fooPrepare := func() { gock.New(urlFoo).Get("/bar").Reply(http.StatusOK).JSON("{}") } + tmpFile, err := os.CreateTemp(os.TempDir(), "api-testing") + if !assert.Nil(t, err) { + return + } + defer func() { + _ = os.Remove(tmpFile.Name()) + }() tests := []struct { name string @@ -101,12 +110,23 @@ func TestRunCommand(t *testing.T) { name: "invalid schema", args: []string{"-p", "testdata/invalid-schema.yaml"}, hasErr: true, + }, { + name: "report file", + prepare: fooPrepare, + args: []string{"-p", simpleSuite, "--report", "md", "--report-file", tmpFile.Name()}, + hasErr: false, + }, { + name: "report file with error", + prepare: fooPrepare, + args: []string{"-p", simpleSuite, "--report", "md", "--report-file", path.Join(tmpFile.Name(), "fake")}, + hasErr: true, }} for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { defer gock.Clean() util.MakeSureNotNil(tt.prepare)() root := &cobra.Command{Use: "root"} + root.SetOut(&bytes.Buffer{}) root.AddCommand(createRunCommand()) root.SetArgs(append([]string{"run"}, tt.args...))