Skip to content

Commit 18bd198

Browse files
authored
feat: support running gRPC test cases (#160)
1 parent e2f2d32 commit 18bd198

22 files changed

+1030
-182
lines changed

cmd/run.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -254,9 +254,9 @@ func (o *runOption) runSuite(loader testing.Loader, dataContext map[string]inter
254254
ctxWithTimeout, _ := context.WithTimeout(ctx, o.requestTimeout)
255255
ctxWithTimeout = context.WithValue(ctxWithTimeout, runner.ContextKey("").ParentDir(), loader.GetContext())
256256

257-
simpleRunner := runner.NewSimpleTestCaseRunner()
258-
simpleRunner.WithTestReporter(o.reporter)
259-
if output, err = simpleRunner.RunTestCase(&testCase, dataContext, ctxWithTimeout); err != nil && !o.requestIgnoreError {
257+
runner := runner.GetTestSuiteRunner(testSuite)
258+
runner.WithTestReporter(o.reporter)
259+
if output, err = runner.RunTestCase(&testCase, dataContext, ctxWithTimeout); err != nil && !o.requestIgnoreError {
260260
err = fmt.Errorf("failed to run '%s', %v", testCase.Name, err)
261261
return
262262
} else {

docs/api-testing-schema.json

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,38 @@
4545
"properties": {
4646
"kind": {
4747
"type": "string",
48-
"enum": ["openapi", "swagger"]
48+
"enum": [
49+
"openapi",
50+
"swagger"
51+
]
4952
},
5053
"url": {
5154
"type": "string",
5255
"qt-uri-protocols": [
53-
"https", "http"
56+
"https",
57+
"http"
5458
]
59+
},
60+
"grpc": {
61+
"type": "object",
62+
"additionalProperties": false,
63+
"properties": {
64+
"import": {
65+
"type": "array",
66+
"items": {
67+
"type": "string"
68+
}
69+
},
70+
"protofile": {
71+
"type": "string"
72+
},
73+
"protoset": {
74+
"type": "string"
75+
},
76+
"serverReflection": {
77+
"type": "boolean"
78+
}
79+
}
5580
}
5681
}
5782
},
@@ -123,10 +148,16 @@
123148
"qt-uri-protocols": [
124149
"https"
125150
]
126-
},
151+
},
127152
"method": {
128153
"type": "string",
129-
"enum": ["GET", "POST", "PUT", "PATCH", "DELETE"]
154+
"enum": [
155+
"GET",
156+
"POST",
157+
"PUT",
158+
"PATCH",
159+
"DELETE"
160+
]
130161
},
131162
"query": {
132163
"description": "HTTP request query",
@@ -175,4 +206,4 @@
175206
"title": "Job"
176207
}
177208
}
178-
}
209+
}

go.mod

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ require (
66
github.com/Masterminds/sprig/v3 v3.2.3
77
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883
88
github.com/antonmedv/expr v1.12.1
9+
github.com/bufbuild/protocompile v0.6.0
910
github.com/cucumber/godog v0.12.6
1011
github.com/ghodss/yaml v1.0.0
1112
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0
@@ -14,12 +15,12 @@ require (
1415
github.com/linuxsuren/go-fake-runtime v0.0.1
1516
github.com/linuxsuren/unstructured v0.0.1
1617
github.com/spf13/cobra v1.6.1
17-
github.com/stretchr/testify v1.8.2
18+
github.com/stretchr/testify v1.8.4
1819
github.com/tidwall/gjson v1.14.4
1920
github.com/xeipuuv/gojsonschema v1.2.0
20-
golang.org/x/sync v0.1.0
21+
golang.org/x/sync v0.3.0
2122
google.golang.org/grpc v1.55.0
22-
google.golang.org/protobuf v1.30.0
23+
google.golang.org/protobuf v1.31.0
2324
gopkg.in/yaml.v3 v3.0.1
2425
)
2526

go.sum

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNg
88
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
99
github.com/antonmedv/expr v1.12.1 h1:GTGrGN1kxxb+le0uQKaFRK8By4cvq1sleUCGE/U6hHg=
1010
github.com/antonmedv/expr v1.12.1/go.mod h1:FPC8iWArxls7axbVLsW+kpg1mz29A1b2M6jt+hZfDkU=
11+
github.com/bufbuild/protocompile v0.6.0 h1:Uu7WiSQ6Yj9DbkdnOe7U4mNKp58y9WDMKDn28/ZlunY=
12+
github.com/bufbuild/protocompile v0.6.0/go.mod h1:YNP35qEYoYGme7QMtz5SBCoN4kL4g12jTtjuzRNdjpE=
1113
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
1214
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
1315
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
@@ -114,7 +116,6 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
114116
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
115117
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
116118
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
117-
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
118119
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
119120
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
120121
github.com/stretchr/testify v1.3.1-0.20190311161405-34c6fa2dc709/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
@@ -123,8 +124,8 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
123124
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
124125
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
125126
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
126-
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
127-
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
127+
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
128+
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
128129
github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM=
129130
github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
130131
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
@@ -153,8 +154,8 @@ golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
153154
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
154155
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
155156
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
156-
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
157-
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
157+
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
158+
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
158159
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
159160
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
160161
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -187,8 +188,8 @@ google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag=
187188
google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8=
188189
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
189190
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
190-
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
191-
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
191+
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
192+
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
192193
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
193194
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
194195
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=

go.work.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,8 @@ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02
667667
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
668668
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
669669
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
670+
github.com/linuxsuren/go-fake-runtime v0.0.0-20230426144714-1a7a0d160d3f h1:TfAzkLxq/agwMBbccTx/f/dlmFWIBLWRGCWjI4IOlK8=
671+
github.com/linuxsuren/go-fake-runtime v0.0.0-20230426144714-1a7a0d160d3f/go.mod h1:zmh6J78hSnWZo68faMA2eKOdaEp8eFbERHi3ZB9xHCQ=
670672
github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA=
671673
github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA=
672674
github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o=
@@ -806,6 +808,8 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ
806808
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
807809
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
808810
golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
811+
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
812+
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
809813
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
810814
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
811815
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

pkg/compare/compare.go

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
MIT License
3+
Copyright (c) 2023 API Testing Authors.
4+
Permission is hereby granted, free of charge, to any person obtaining a copy
5+
of this software and associated documentation files (the "Software"), to deal
6+
in the Software without restriction, including without limitation the rights
7+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
copies of the Software, and to permit persons to whom the Software is
9+
furnished to do so, subject to the following conditions:
10+
The above copyright notice and this permission notice shall be included in all
11+
copies or substantial portions of the Software.
12+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
18+
SOFTWARE.
19+
*/
20+
21+
// Package compare provides basic functions to compare JSON object and array.
22+
// Currently we use gjson to store the JSON data. Please check tidwall/gjson.
23+
package compare
24+
25+
import (
26+
"fmt"
27+
"reflect"
28+
"strconv"
29+
30+
"github.com/tidwall/gjson"
31+
)
32+
33+
// Object compares two JSON object.
34+
func Object(field string, expect, actul map[string]gjson.Result) error {
35+
var errs error
36+
for k, ev := range expect {
37+
av, ok := actul[k]
38+
if !ok {
39+
errs = JoinErr(errs, newNoEqualErr(field, fmt.Errorf("field %s is not exist", k)))
40+
continue
41+
}
42+
43+
err := Element(k, ev, av)
44+
if err != nil {
45+
errs = JoinErr(errs, newNoEqualErr(field, err))
46+
}
47+
}
48+
return errs
49+
}
50+
51+
// Array compares two JSON Array.
52+
func Array(field string, expect, actul []gjson.Result) error {
53+
var errs error
54+
if l1, l2 := len(expect), len(actul); l1 != l2 {
55+
return newNoEqualErr(field, fmt.Errorf("length is not equal, expect %v fields but got %v", l1, l2))
56+
}
57+
58+
for i := range expect {
59+
err := Element(strconv.Itoa(i), expect[i], actul[i])
60+
if err != nil {
61+
errs = JoinErr(errs, newNoEqualErr(field, err))
62+
}
63+
}
64+
return errs
65+
}
66+
67+
// Element compares two JSON Element.
68+
func Element(field string, expect, actul gjson.Result) error {
69+
if expect.Type != actul.Type {
70+
return newNoEqualErr(field, fmt.Errorf("expect type %s but got %v", expect.Type.String(), actul.Type.String()))
71+
}
72+
73+
if expect.IsObject() {
74+
return Object(field, expect.Map(), actul.Map())
75+
}
76+
77+
if expect.IsArray() {
78+
return Array(field, expect.Array(), actul.Array())
79+
}
80+
81+
if !reflect.DeepEqual(expect.Value(), actul.Value()) {
82+
return newNoEqualErr(field, fmt.Errorf("expect %v but got %v", expect.Value(), actul.Value()))
83+
}
84+
85+
return nil
86+
}

pkg/compare/compare_test.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
MIT License
3+
Copyright (c) 2023 API Testing Authors.
4+
Permission is hereby granted, free of charge, to any person obtaining a copy
5+
of this software and associated documentation files (the "Software"), to deal
6+
in the Software without restriction, including without limitation the rights
7+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
copies of the Software, and to permit persons to whom the Software is
9+
furnished to do so, subject to the following conditions:
10+
The above copyright notice and this permission notice shall be included in all
11+
copies or substantial portions of the Software.
12+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
18+
SOFTWARE.
19+
*/
20+
21+
package compare
22+
23+
import (
24+
"testing"
25+
26+
"github.com/stretchr/testify/assert"
27+
"github.com/tidwall/gjson"
28+
)
29+
30+
func TestElement(t *testing.T) {
31+
exp := `{
32+
"data": [
33+
{
34+
"key": "hell",
35+
"value": "func() strin"
36+
}
37+
]
38+
}
39+
`
40+
act := `
41+
{
42+
"data": [
43+
{
44+
"key": "hello",
45+
"value": "func() string"
46+
}
47+
]
48+
}`
49+
expect := gjson.Parse(exp)
50+
actul := gjson.Parse(act)
51+
52+
err := Element("TestElement", expect, actul)
53+
54+
expmsg1 := "compare: field TestElement.data.0.value: expect func() strin but got func() string"
55+
expmsg2 := "compare: field TestElement.data.0.key: expect hell but got hello"
56+
assert.Contains(t, err.Error(), expmsg1)
57+
assert.Contains(t, err.Error(), expmsg2)
58+
}

0 commit comments

Comments
 (0)