diff --git a/pkg/apispec/fake.go b/pkg/apispec/fake.go new file mode 100644 index 00000000..dc956092 --- /dev/null +++ b/pkg/apispec/fake.go @@ -0,0 +1,27 @@ +package apispec + +type fakeAPISpec struct { + apis [][]string +} + +// NewFakeAPISpec creates a new instance of fakeAPISpec +func NewFakeAPISpec(apis [][]string) APIConverage { + return &fakeAPISpec{apis: apis} +} + +// HaveAPI is fake method +func (f *fakeAPISpec) HaveAPI(path, method string) (exist bool) { + for _, item := range f.apis { + if len(item) >= 2 && item[0] == path && item[1] == method { + exist = true + break + } + } + return +} + +// APICount is fake method +func (f *fakeAPISpec) APICount() (count int) { + count = len(f.apis) + return +} diff --git a/pkg/apispec/fake_test.go b/pkg/apispec/fake_test.go new file mode 100644 index 00000000..cdab3105 --- /dev/null +++ b/pkg/apispec/fake_test.go @@ -0,0 +1,43 @@ +package apispec_test + +import ( + "testing" + + "github.com/linuxsuren/api-testing/pkg/apispec" + "github.com/stretchr/testify/assert" +) + +func TestFakeAPISpec(t *testing.T) { + tests := []struct { + name string + data [][]string + path, method string + expectExist bool + expectCount int + }{{ + name: "normal", + data: [][]string{{ + "/api", "get", + }}, + path: "/api", + method: "get", + expectExist: true, + expectCount: 1, + }, { + name: "empty", + data: [][]string{}, + path: "/api", + method: "post", + expectExist: false, + expectCount: 0, + }} + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + coverage := apispec.NewFakeAPISpec(tt.data) + exist := coverage.HaveAPI(tt.path, tt.method) + count := coverage.APICount() + assert.Equal(t, tt.expectExist, exist) + assert.Equal(t, tt.expectCount, count) + }) + } +} diff --git a/pkg/runner/simple.go b/pkg/runner/http.go similarity index 83% rename from pkg/runner/simple.go rename to pkg/runner/http.go index e3323af0..cef40154 100644 --- a/pkg/runner/simple.go +++ b/pkg/runner/http.go @@ -14,7 +14,6 @@ import ( "github.com/andreyvit/diff" "github.com/antonmedv/expr" "github.com/antonmedv/expr/vm" - "github.com/linuxsuren/api-testing/pkg/apispec" "github.com/linuxsuren/api-testing/pkg/runner/kubernetes" "github.com/linuxsuren/api-testing/pkg/testing" fakeruntime "github.com/linuxsuren/go-fake-runtime" @@ -71,54 +70,6 @@ func (w *defaultLevelWriter) Debug(format string, a ...any) { w.Fprintf(w.Writer, 7, format, a...) } -// TestCaseRunner represents a test case runner -type TestCaseRunner interface { - RunTestCase(testcase *testing.TestCase, dataContext interface{}, ctx context.Context) (output interface{}, err error) - WithOutputWriter(io.Writer) TestCaseRunner - WithWriteLevel(level string) TestCaseRunner - WithTestReporter(TestReporter) TestCaseRunner - WithExecer(fakeruntime.Execer) TestCaseRunner -} - -// ReportRecord represents the raw data of a HTTP request -type ReportRecord struct { - Method string - API string - Body string - BeginTime time.Time - EndTime time.Time - Error error -} - -// Duration returns the duration between begin and end time -func (r *ReportRecord) Duration() time.Duration { - return r.EndTime.Sub(r.BeginTime) -} - -// ErrorCount returns the count number of errors -func (r *ReportRecord) ErrorCount() int { - if r.Error == nil { - return 0 - } - return 1 -} - -// GetErrorMessage returns the error message -func (r *ReportRecord) GetErrorMessage() string { - if r.ErrorCount() > 0 { - return r.Body - } else { - return "" - } -} - -// NewReportRecord creates a record, and set the begin time to be now -func NewReportRecord() *ReportRecord { - return &ReportRecord{ - BeginTime: time.Now(), - } -} - // ReportResult represents the report result of a set of the same API requests type ReportResult struct { API string @@ -151,19 +102,6 @@ func (r ReportResultSlice) Swap(i, j int) { r[j] = tmp } -// ReportResultWriter is the interface of the report writer -type ReportResultWriter interface { - Output([]ReportResult) error - WithAPIConverage(apiConverage apispec.APIConverage) ReportResultWriter -} - -// TestReporter is the interface of the report -type TestReporter interface { - PutRecord(*ReportRecord) - GetAllRecords() []*ReportRecord - ExportAllReportResults() (ReportResultSlice, error) -} - type simpleTestCaseRunner struct { testReporter TestReporter writer io.Writer @@ -318,18 +256,6 @@ func (r *simpleTestCaseRunner) WithExecer(execer fakeruntime.Execer) TestCaseRun return r } -func (r *simpleTestCaseRunner) doCleanPrepare(testcase *testing.TestCase) (err error) { - count := len(testcase.Before.Items) - for i := count - 1; i >= 0; i-- { - item := testcase.Before.Items[i] - - if err = r.execer.RunCommand("kubectl", "delete", "-f", item); err != nil { - return - } - } - return -} - func expectInt(name string, expect, actual int) (err error) { if expect != actual { err = fmt.Errorf("case: %s, expect %d, actual %d", name, expect, actual) diff --git a/pkg/runner/simple_test.go b/pkg/runner/http_test.go similarity index 100% rename from pkg/runner/simple_test.go rename to pkg/runner/http_test.go diff --git a/pkg/runner/reporter.go b/pkg/runner/reporter.go new file mode 100644 index 00000000..a9069f1f --- /dev/null +++ b/pkg/runner/reporter.go @@ -0,0 +1,49 @@ +package runner + +import "time" + +// TestReporter is the interface of the report +type TestReporter interface { + PutRecord(*ReportRecord) + GetAllRecords() []*ReportRecord + ExportAllReportResults() (ReportResultSlice, error) +} + +// ReportRecord represents the raw data of a HTTP request +type ReportRecord struct { + Method string + API string + Body string + BeginTime time.Time + EndTime time.Time + Error error +} + +// Duration returns the duration between begin and end time +func (r *ReportRecord) Duration() time.Duration { + return r.EndTime.Sub(r.BeginTime) +} + +// ErrorCount returns the count number of errors +func (r *ReportRecord) ErrorCount() int { + if r.Error == nil { + return 0 + } + return 1 +} + +// GetErrorMessage returns the error message +func (r *ReportRecord) GetErrorMessage() string { + if r.ErrorCount() > 0 { + return r.Body + } else { + return "" + } +} + +// NewReportRecord creates a record, and set the begin time to be now +func NewReportRecord() *ReportRecord { + return &ReportRecord{ + BeginTime: time.Now(), + } +} diff --git a/pkg/runner/runner.go b/pkg/runner/runner.go new file mode 100644 index 00000000..7a57f613 --- /dev/null +++ b/pkg/runner/runner.go @@ -0,0 +1,18 @@ +package runner + +import ( + "context" + "io" + + "github.com/linuxsuren/api-testing/pkg/testing" + fakeruntime "github.com/linuxsuren/go-fake-runtime" +) + +// TestCaseRunner represents a test case runner +type TestCaseRunner interface { + RunTestCase(testcase *testing.TestCase, dataContext interface{}, ctx context.Context) (output interface{}, err error) + WithOutputWriter(io.Writer) TestCaseRunner + WithWriteLevel(level string) TestCaseRunner + WithTestReporter(TestReporter) TestCaseRunner + WithExecer(fakeruntime.Execer) TestCaseRunner +} diff --git a/pkg/runner/writer.go b/pkg/runner/writer.go new file mode 100644 index 00000000..187a5076 --- /dev/null +++ b/pkg/runner/writer.go @@ -0,0 +1,9 @@ +package runner + +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 +} diff --git a/pkg/runner/writer_std_test.go b/pkg/runner/writer_std_test.go index 9a7561e6..cb912ea5 100644 --- a/pkg/runner/writer_std_test.go +++ b/pkg/runner/writer_std_test.go @@ -4,16 +4,18 @@ import ( "bytes" "testing" + "github.com/linuxsuren/api-testing/pkg/apispec" "github.com/linuxsuren/api-testing/pkg/runner" "github.com/stretchr/testify/assert" ) func TestNewStdResultWriter(t *testing.T) { tests := []struct { - name string - buf *bytes.Buffer - results []runner.ReportResult - expect string + name string + buf *bytes.Buffer + apiConverage apispec.APIConverage + results []runner.ReportResult + expect string }{{ name: "result is nil", buf: new(bytes.Buffer), @@ -23,8 +25,11 @@ func TestNewStdResultWriter(t *testing.T) { }, { name: "have one item", buf: new(bytes.Buffer), + apiConverage: apispec.NewFakeAPISpec([][]string{{ + "/api", "GET", + }}), results: []runner.ReportResult{{ - API: "api", + API: "/api", Average: 1, Max: 1, Min: 1, @@ -33,7 +38,9 @@ func TestNewStdResultWriter(t *testing.T) { Error: 0, }}, expect: `API Average Max Min QPS Count Error -api 1ns 1ns 1ns 10 1 0 +/api 1ns 1ns 1ns 10 1 0 + +API Coverage: 1/1 `, }, { name: "have errors", @@ -76,7 +83,7 @@ api 1ns 1ns 1ns 10 1 0 return } - writer.WithAPIConverage(nil) + writer.WithAPIConverage(tt.apiConverage) err := writer.Output(tt.results) assert.Nil(t, err) assert.Equal(t, tt.expect, tt.buf.String())