From 1c230918058008b90539b93ba090b4c52b96af16 Mon Sep 17 00:00:00 2001 From: rick Date: Tue, 24 Dec 2024 21:12:38 +0800 Subject: [PATCH] chore: support to print test case count in stdout --- cmd/run.go | 10 ++- pkg/apispec/fake.go | 2 +- pkg/apispec/swagger.go | 4 +- pkg/runner/writer.go | 2 +- pkg/runner/writer_github_pr_comment.go | 2 +- pkg/runner/writer_github_pr_comment_test.go | 2 +- pkg/runner/writer_grpc.go | 2 +- pkg/runner/writer_html.go | 4 +- pkg/runner/writer_html_test.go | 2 +- pkg/runner/writer_http.go | 2 +- pkg/runner/writer_json.go | 2 +- pkg/runner/writer_json_test.go | 2 +- pkg/runner/writer_markdown.go | 4 +- pkg/runner/writer_markdown_test.go | 12 ++-- pkg/runner/writer_pdf.go | 30 +++++---- pkg/runner/writer_pdf_test.go | 69 +++++++++++++++++++++ pkg/runner/writer_std.go | 17 ++--- pkg/runner/writer_std_test.go | 8 ++- 18 files changed, 130 insertions(+), 46 deletions(-) create mode 100644 pkg/runner/writer_pdf_test.go diff --git a/cmd/run.go b/cmd/run.go index f2fa00c5..bce1da18 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -1,5 +1,5 @@ /* -Copyright 2023 API Testing Authors. +Copyright 2023-2024 API Testing Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -163,6 +163,10 @@ func (o *runOption) preRunE(cmd *cobra.Command, args []string) (err error) { case "", "std": o.reportWriter = runner.NewResultWriter(writer) case "pdf": + if o.reportFile == "" { + err = fmt.Errorf("report file is required for pdf report") + return + } o.reportWriter = runner.NewPDFResultWriter(writer) case "prometheus": if o.reportFile == "" { @@ -189,7 +193,7 @@ func (o *runOption) preRunE(cmd *cobra.Command, args []string) (err error) { var swaggerAPI apispec.SwaggerAPI if o.swaggerURL != "" { if swaggerAPI.Swagger, err = apispec.ParseURLToSwagger(o.swaggerURL); err == nil { - o.reportWriter.WithAPIConverage(&swaggerAPI) + o.reportWriter.WithAPICoverage(&swaggerAPI) } } } @@ -360,7 +364,7 @@ func (o *runOption) runSuite(loader testing.Loader, dataContext map[string]inter runLogger.Info("run test suite", "name", testSuite.Name, "filter", caseFilter) for _, testCase := range testSuite.Items { if caseFilterObj != nil { - if filter, ok := caseFilterObj.([]string); ok && len(filter) > 0{ + if filter, ok := caseFilterObj.([]string); ok && len(filter) > 0 { match := false for _, ff := range filter { if strings.Contains(testCase.Name, ff) { diff --git a/pkg/apispec/fake.go b/pkg/apispec/fake.go index 061492a1..f9d7ae15 100644 --- a/pkg/apispec/fake.go +++ b/pkg/apispec/fake.go @@ -21,7 +21,7 @@ type fakeAPISpec struct { } // NewFakeAPISpec creates a new instance of fakeAPISpec -func NewFakeAPISpec(apis [][]string) APIConverage { +func NewFakeAPISpec(apis [][]string) APICoverage { return &fakeAPISpec{apis: apis} } diff --git a/pkg/apispec/swagger.go b/pkg/apispec/swagger.go index f066e7dd..2b305365 100644 --- a/pkg/apispec/swagger.go +++ b/pkg/apispec/swagger.go @@ -1,5 +1,5 @@ /* -Copyright 2023 API Testing Authors. +Copyright 2023-2024 API Testing Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -24,7 +24,7 @@ import ( "strings" ) -type APIConverage interface { +type APICoverage interface { HaveAPI(path, method string) (exist bool) APICount() (count int) } diff --git a/pkg/runner/writer.go b/pkg/runner/writer.go index b92f86b8..2f31b459 100644 --- a/pkg/runner/writer.go +++ b/pkg/runner/writer.go @@ -21,6 +21,6 @@ import "github.com/linuxsuren/api-testing/pkg/apispec" // ReportResultWriter is the interface of the report writer type ReportResultWriter interface { Output([]ReportResult) error - WithAPIConverage(apiConverage apispec.APIConverage) ReportResultWriter + WithAPICoverage(apiCoverage apispec.APICoverage) ReportResultWriter WithResourceUsage([]ResourceUsage) ReportResultWriter } diff --git a/pkg/runner/writer_github_pr_comment.go b/pkg/runner/writer_github_pr_comment.go index e46a7617..8eccc511 100644 --- a/pkg/runner/writer_github_pr_comment.go +++ b/pkg/runner/writer_github_pr_comment.go @@ -185,7 +185,7 @@ func (w *githubPRCommentWriter) setHeader(req *http.Request) { req.Header.Set("X-GitHub-Api-Version", "2022-11-28") } -func (w *githubPRCommentWriter) WithAPIConverage(apiConverage apispec.APIConverage) (r ReportResultWriter) { +func (w *githubPRCommentWriter) WithAPICoverage(apiConverage apispec.APICoverage) (r ReportResultWriter) { // not have this feature return } diff --git a/pkg/runner/writer_github_pr_comment_test.go b/pkg/runner/writer_github_pr_comment_test.go index 836e3eec..9ada44b0 100644 --- a/pkg/runner/writer_github_pr_comment_test.go +++ b/pkg/runner/writer_github_pr_comment_test.go @@ -60,7 +60,7 @@ func TestGithubPRCommentWriter(t *testing.T) { err = writer.Output(nil) assert.NoError(t, err) - assert.Nil(t, writer.WithAPIConverage(nil)) + assert.Nil(t, writer.WithAPICoverage(nil)) assert.NotNil(t, writer.WithResourceUsage(nil)) }) diff --git a/pkg/runner/writer_grpc.go b/pkg/runner/writer_grpc.go index 57f50985..b38e0b9e 100644 --- a/pkg/runner/writer_grpc.go +++ b/pkg/runner/writer_grpc.go @@ -111,7 +111,7 @@ func getConnection(host string) (conn *grpc.ClientConn, err error) { } // WithAPIConverage sets the api coverage -func (w *grpcResultWriter) WithAPIConverage(apiConverage apispec.APIConverage) ReportResultWriter { +func (w *grpcResultWriter) WithAPICoverage(apiConverage apispec.APICoverage) ReportResultWriter { return w } diff --git a/pkg/runner/writer_html.go b/pkg/runner/writer_html.go index eb700dfa..870baec9 100644 --- a/pkg/runner/writer_html.go +++ b/pkg/runner/writer_html.go @@ -26,7 +26,7 @@ import ( type htmlResultWriter struct { writer io.Writer - apiConverage apispec.APIConverage + apiConverage apispec.APICoverage } // NewHTMLResultWriter creates a new htmlResultWriter @@ -40,7 +40,7 @@ func (w *htmlResultWriter) Output(result []ReportResult) (err error) { } // WithAPIConverage sets the api coverage -func (w *htmlResultWriter) WithAPIConverage(apiConverage apispec.APIConverage) ReportResultWriter { +func (w *htmlResultWriter) WithAPICoverage(apiConverage apispec.APICoverage) ReportResultWriter { w.apiConverage = apiConverage return w } diff --git a/pkg/runner/writer_html_test.go b/pkg/runner/writer_html_test.go index 44beda03..37c0b56b 100644 --- a/pkg/runner/writer_html_test.go +++ b/pkg/runner/writer_html_test.go @@ -48,7 +48,7 @@ func TestHTMLResultWriter(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { w := runner.NewHTMLResultWriter(tt.buf) - w.WithAPIConverage(nil) + w.WithAPICoverage(nil) err := w.Output(tt.results) assert.NoError(t, err) assert.Equal(t, tt.expect, tt.buf.String()) diff --git a/pkg/runner/writer_http.go b/pkg/runner/writer_http.go index 5faf40df..138dbad3 100644 --- a/pkg/runner/writer_http.go +++ b/pkg/runner/writer_http.go @@ -141,7 +141,7 @@ func (w *httpResultWriter) Output(result []ReportResult) (err error) { var defaultTemplate string // WithAPIConverage sets the api coverage -func (w *httpResultWriter) WithAPIConverage(apiConverage apispec.APIConverage) ReportResultWriter { +func (w *httpResultWriter) WithAPICoverage(apiConverage apispec.APICoverage) ReportResultWriter { return w } diff --git a/pkg/runner/writer_json.go b/pkg/runner/writer_json.go index c5140b72..a874baf0 100644 --- a/pkg/runner/writer_json.go +++ b/pkg/runner/writer_json.go @@ -44,7 +44,7 @@ func (w *jsonResultWriter) Output(result []ReportResult) (err error) { } // WithAPIConverage sets the api coverage -func (w *jsonResultWriter) WithAPIConverage(apiConverage apispec.APIConverage) ReportResultWriter { +func (w *jsonResultWriter) WithAPICoverage(apiConverage apispec.APICoverage) ReportResultWriter { return w } diff --git a/pkg/runner/writer_json_test.go b/pkg/runner/writer_json_test.go index 83497dea..bafb77a4 100644 --- a/pkg/runner/writer_json_test.go +++ b/pkg/runner/writer_json_test.go @@ -28,7 +28,7 @@ import ( func TestJSONResultWriter(t *testing.T) { buf := new(bytes.Buffer) writer := runner.NewJSONResultWriter(buf) - writer.WithAPIConverage(nil) + writer.WithAPICoverage(nil) err := writer.Output([]runner.ReportResult{{ Name: "foo", diff --git a/pkg/runner/writer_markdown.go b/pkg/runner/writer_markdown.go index 1e81793c..0a8af5ba 100644 --- a/pkg/runner/writer_markdown.go +++ b/pkg/runner/writer_markdown.go @@ -26,7 +26,7 @@ import ( type markdownResultWriter struct { writer io.Writer - apiConverage apispec.APIConverage + apiConverage apispec.APICoverage resourceUsage []ResourceUsage } @@ -59,7 +59,7 @@ func (w *markdownResultWriter) Output(result []ReportResult) (err error) { } // WithAPIConverage sets the api coverage -func (w *markdownResultWriter) WithAPIConverage(apiConverage apispec.APIConverage) ReportResultWriter { +func (w *markdownResultWriter) WithAPICoverage(apiConverage apispec.APICoverage) ReportResultWriter { w.apiConverage = apiConverage return w } diff --git a/pkg/runner/writer_markdown_test.go b/pkg/runner/writer_markdown_test.go index 06056338..345eb18c 100644 --- a/pkg/runner/writer_markdown_test.go +++ b/pkg/runner/writer_markdown_test.go @@ -48,7 +48,7 @@ func TestMarkdownWriter(t *testing.T) { t.Run("short", func(t *testing.T) { buf := new(bytes.Buffer) writer := runner.NewMarkdownResultWriter(buf) - writer.WithAPIConverage(nil) + writer.WithAPICoverage(nil) err := writer.Output(createSlice(sample, 2)) assert.Nil(t, err) assert.Equal(t, `There are 2 test cases, failed count 0: @@ -62,7 +62,7 @@ func TestMarkdownWriter(t *testing.T) { t.Run("long", func(t *testing.T) { buf := new(bytes.Buffer) writer := runner.NewMarkdownResultWriter(buf) - writer.WithAPIConverage(nil) + writer.WithAPICoverage(nil) err := writer.Output(createSlice(sample, 8)) assert.Nil(t, err) assert.Equal(t, `There are 8 test cases, failed count 0: @@ -86,7 +86,7 @@ func TestMarkdownWriter(t *testing.T) { t.Run("long, there are error cases", func(t *testing.T) { buf := new(bytes.Buffer) writer := runner.NewMarkdownResultWriter(buf) - writer.WithAPIConverage(nil) + writer.WithAPICoverage(nil) err := writer.Output(append(createSlice(sample, 8), errSample)) assert.Nil(t, err) assert.Equal(t, `There are 9 test cases, failed count 1: @@ -115,7 +115,7 @@ func TestMarkdownWriter(t *testing.T) { t.Run("with resource usage", func(t *testing.T) { buf := new(bytes.Buffer) writer := runner.NewMarkdownResultWriter(buf) - writer.WithAPIConverage(nil) + writer.WithAPICoverage(nil) writer.WithResourceUsage([]runner.ResourceUsage{{ CPU: 1, Memory: 1, @@ -137,7 +137,7 @@ Resource usage: t.Run("have error message", func(t *testing.T) { buf := new(bytes.Buffer) writer := runner.NewMarkdownResultWriter(buf) - writer.WithAPIConverage(nil) + writer.WithAPICoverage(nil) result := sample result.LastErrorMessage = "error happend" err := writer.Output(createSlice(result, 2)) @@ -159,7 +159,7 @@ Resource usage: t.Run("with api converage", func(t *testing.T) { buf := new(bytes.Buffer) writer := runner.NewMarkdownResultWriter(buf) - writer.WithAPIConverage(apispec.NewFakeAPISpec([][]string{{ + writer.WithAPICoverage(apispec.NewFakeAPISpec([][]string{{ "api", "GET", }})) err := writer.Output(createSlice(sample, 2)) diff --git a/pkg/runner/writer_pdf.go b/pkg/runner/writer_pdf.go index 40a77980..857007d1 100644 --- a/pkg/runner/writer_pdf.go +++ b/pkg/runner/writer_pdf.go @@ -1,5 +1,5 @@ /* -Copyright 2023 API Testing Authors. +Copyright 2023-2024 API Testing Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -18,9 +18,9 @@ package runner import ( _ "embed" + "fmt" "github.com/linuxsuren/api-testing/pkg/logging" - "fmt" "io" "strconv" @@ -44,15 +44,24 @@ func NewPDFResultWriter(writer io.Writer) ReportResultWriter { // Output writes the PDF base report to target writer func (w *pdfResultWriter) Output(result []ReportResult) (err error) { - pdf := gopdf.GoPdf{} pdf.Start(gopdf.Config{PageSize: *gopdf.PageSizeA4}) - writeLogger.Info(findfont.List()[len(findfont.List())-1]) - fontPath, err := findfont.Find("DejaVuSerif.ttf") + + var fontPath string + fontPath, err = findfont.Find("DejaVuSerif.ttf") if err != nil { - panic(err) + writeLogger.Error(err, "Failed to find 'ttf'", "path", fontPath) + + if len(findfont.List()) == 0 { + err = fmt.Errorf("cannot find font") + writeLogger.Error(err, "No font found") + return + } + + fontPath = findfont.List()[0] } - fmt.Printf("Found 'ttf' in '%s'\n", fontPath) + + writeLogger.Info("Found font 'ttf'", "path", fontPath) err = pdf.AddTTFFont("wts11", fontPath) if err != nil { writeLogger.Info(err.Error()) @@ -65,7 +74,6 @@ func (w *pdfResultWriter) Output(result []ReportResult) (err error) { } pdf.AddHeader(func() { - }) pdf.AddFooter(func() { const X_bias float64 = 101 @@ -103,16 +111,14 @@ func (w *pdfResultWriter) Output(result []ReportResult) (err error) { if api.Error != 0 { pdf.Image("../pkg/runner/data/imgs/warn.jpg", 30, Y_start+line_bias*6-5, nil) } - } - fmt.Fprint(w.writer, "Report is OK!") - pdf.WritePdf("Report.pdf") + _, err = pdf.WriteTo(w.writer) return } // WithAPIConverage sets the api coverage -func (w *pdfResultWriter) WithAPIConverage(apiConverage apispec.APIConverage) ReportResultWriter { +func (w *pdfResultWriter) WithAPICoverage(apiConverage apispec.APICoverage) ReportResultWriter { return w } diff --git a/pkg/runner/writer_pdf_test.go b/pkg/runner/writer_pdf_test.go new file mode 100644 index 00000000..4773309f --- /dev/null +++ b/pkg/runner/writer_pdf_test.go @@ -0,0 +1,69 @@ +/* +Copyright 2024 API Testing Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package runner + +import ( + "bytes" + "github.com/stretchr/testify/assert" + "io" + "testing" +) + +func TestPDF(t *testing.T) { + tests := []struct { + name string + buf io.Writer + results []ReportResult + verify func(t *testing.T) + hasErr bool + }{{ + name: "normal", + buf: new(bytes.Buffer), + results: []ReportResult{{ + Name: "/api", + API: "/api", + Average: 1, + Max: 1, + Min: 1, + QPS: 10, + Count: 1, + Error: 0, + }}, + verify: func(t *testing.T) { + + }, + }} + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + writer := NewPDFResultWriter(tt.buf) + if !assert.NotNil(t, writer) { + return + } + + err := writer.Output(tt.results) + if tt.hasErr { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + + tt.verify(t) + writer.WithResourceUsage(nil) + writer.WithAPICoverage(nil) + }) + } +} diff --git a/pkg/runner/writer_std.go b/pkg/runner/writer_std.go index 3c5b09f3..999b1f82 100644 --- a/pkg/runner/writer_std.go +++ b/pkg/runner/writer_std.go @@ -1,5 +1,5 @@ /* -Copyright 2023 API Testing Authors. +Copyright 2023-2024 API Testing Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -26,7 +26,7 @@ import ( type stdResultWriter struct { writer io.Writer - apiConverage apispec.APIConverage + apiConverage apispec.APICoverage } // NewResultWriter creates a result writer with the specific io.Writer @@ -42,9 +42,9 @@ func NewDiscardResultWriter() ReportResultWriter { // Output writer the report to target writer func (w *stdResultWriter) Output(results []ReportResult) error { var errResults []ReportResult - fmt.Fprintf(w.writer, "Name Average Max Min QPS Count Error\n") + _, _ = fmt.Fprintf(w.writer, "Name Average Max Min QPS Count Error\n") for _, r := range results { - fmt.Fprintf(w.writer, "%s %v %v %v %d %d %d\n", r.Name, r.Average, r.Max, + _, _ = fmt.Fprintf(w.writer, "%s %v %v %v %d %d %d\n", r.Name, r.Average, r.Max, r.Min, r.QPS, r.Count, r.Error) if r.Error > 0 && r.LastErrorMessage != "" { errResults = append(errResults, r) @@ -52,15 +52,16 @@ func (w *stdResultWriter) Output(results []ReportResult) error { } for _, r := range errResults { - fmt.Fprintf(w.writer, "%s error: %s\n", r.API, r.LastErrorMessage) + _, _ = fmt.Fprintf(w.writer, "%s error: %s\n", r.API, r.LastErrorMessage) } + _, _ = fmt.Fprintf(w.writer, "Test case count: %d\n", len(results)) apiConveragePrint(results, w.apiConverage, w.writer) return nil } // WithAPIConverage sets the api coverage -func (w *stdResultWriter) WithAPIConverage(apiConverage apispec.APIConverage) ReportResultWriter { +func (w *stdResultWriter) WithAPICoverage(apiConverage apispec.APICoverage) ReportResultWriter { w.apiConverage = apiConverage return w } @@ -69,14 +70,14 @@ func (w *stdResultWriter) WithResourceUsage([]ResourceUsage) ReportResultWriter return w } -func apiConveragePrint(result []ReportResult, apiConverage apispec.APIConverage, w io.Writer) { +func apiConveragePrint(result []ReportResult, apiConverage apispec.APICoverage, w io.Writer) { covered, total := apiConverageCount(result, apiConverage) if total > 0 { fmt.Fprintf(w, "\nAPI Coverage: %d/%d\n", covered, total) } } -func apiConverageCount(result []ReportResult, apiConverage apispec.APIConverage) (covered, total int) { +func apiConverageCount(result []ReportResult, apiConverage apispec.APICoverage) (covered, total int) { if apiConverage == nil { return } diff --git a/pkg/runner/writer_std_test.go b/pkg/runner/writer_std_test.go index 0e704c3c..5c4e19df 100644 --- a/pkg/runner/writer_std_test.go +++ b/pkg/runner/writer_std_test.go @@ -29,7 +29,7 @@ func TestNewStdResultWriter(t *testing.T) { tests := []struct { name string buf *bytes.Buffer - apiConverage apispec.APIConverage + apiConverage apispec.APICoverage results []runner.ReportResult expect string }{{ @@ -37,6 +37,7 @@ func TestNewStdResultWriter(t *testing.T) { buf: new(bytes.Buffer), results: nil, expect: `Name Average Max Min QPS Count Error +Test case count: 0 `, }, { name: "have one item", @@ -56,6 +57,7 @@ func TestNewStdResultWriter(t *testing.T) { }}, expect: `Name Average Max Min QPS Count Error /api 1ns 1ns 1ns 10 1 0 +Test case count: 1 API Coverage: 1/1 `, @@ -76,6 +78,7 @@ API Coverage: 1/1 expect: `Name Average Max Min QPS Count Error api 1ns 1ns 1ns 10 1 1 api error: error +Test case count: 1 `, }, { name: "have no errors but with message", @@ -93,6 +96,7 @@ api error: error }}, expect: `Name Average Max Min QPS Count Error api 1ns 1ns 1ns 10 1 0 +Test case count: 1 `, }} for _, tt := range tests { @@ -102,7 +106,7 @@ api 1ns 1ns 1ns 10 1 0 return } - writer.WithAPIConverage(tt.apiConverage) + writer.WithAPICoverage(tt.apiConverage) err := writer.Output(tt.results) assert.Nil(t, err) assert.Equal(t, tt.expect, tt.buf.String())