Skip to content

Commit 45a4d51

Browse files
authored
feat: support to validate the YAML file via schema (#49)
1 parent 4944157 commit 45a4d51

File tree

12 files changed

+73
-1076
lines changed

12 files changed

+73
-1076
lines changed

cmd/root.go

+10
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,13 @@ func NewRootCmd(execer fakeruntime.Execer, gRPCServer gRPCServer) (c *cobra.Comm
2222
createServiceCommand(execer))
2323
return
2424
}
25+
26+
type printer interface {
27+
Println(i ...interface{})
28+
}
29+
30+
func println(printer printer, err error, i ...interface{}) {
31+
if err != nil {
32+
printer.Println(i...)
33+
}
34+
}

cmd/run.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -114,13 +114,13 @@ func (o *runOption) runE(cmd *cobra.Command, args []string) (err error) {
114114
}
115115

116116
// print the report
117-
if results, reportErr := o.reporter.ExportAllReportResults(); reportErr == nil {
118-
if reportErr = o.reportWriter.Output(results); reportErr != nil {
119-
cmd.Println("failed to Output all reports", reportErr)
120-
}
121-
} else {
122-
cmd.Println("failed to export all reports", reportErr)
117+
var reportErr error
118+
var results runner.ReportResultSlice
119+
if results, reportErr = o.reporter.ExportAllReportResults(); reportErr == nil {
120+
outputErr := o.reportWriter.Output(results)
121+
println(cmd, outputErr, "failed to Output all reports", outputErr)
123122
}
123+
println(cmd, reportErr, "failed to export all reports", reportErr)
124124
return
125125
}
126126

cmd/run_test.go

+14
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package cmd
22

33
import (
4+
"bytes"
45
"context"
6+
"errors"
57
"net/http"
68
"testing"
79
"time"
@@ -175,5 +177,17 @@ func TestPreRunE(t *testing.T) {
175177
}
176178
}
177179

180+
func TestPrinter(t *testing.T) {
181+
buf := new(bytes.Buffer)
182+
c := &cobra.Command{}
183+
c.SetOutput(buf)
184+
185+
println(c, nil, "foo")
186+
assert.Empty(t, buf.String())
187+
188+
println(c, errors.New("bar"), "foo")
189+
assert.Equal(t, "foo\n", buf.String())
190+
}
191+
178192
const urlFoo = "http://foo"
179193
const simpleSuite = "testdata/simple-suite.yaml"

cmd/testdata/simple-suite.yaml

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
name: Simple
2-
api: http://foo/
2+
api: http://foo
33
items:
44
- request:
55
api: /bar
6+
name: bar

go.mod

+7-6
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,29 @@ 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/ghodss/yaml v1.0.0
10+
github.com/golang/protobuf v1.5.2
911
github.com/h2non/gock v1.2.0
12+
github.com/invopop/jsonschema v0.7.0
13+
github.com/linuxsuren/go-fake-runtime v0.0.0-20230413085645-15e77ab55dbd
1014
github.com/linuxsuren/unstructured v0.0.1
1115
github.com/spf13/cobra v1.6.1
1216
github.com/stretchr/testify v1.8.2
17+
github.com/xeipuuv/gojsonschema v1.2.0
1318
golang.org/x/sync v0.1.0
1419
google.golang.org/grpc v1.54.0
15-
google.golang.org/protobuf v1.30.0
16-
gopkg.in/yaml.v2 v2.4.0
1720
)
1821

1922
require (
2023
github.com/Masterminds/goutils v1.1.1 // indirect
2124
github.com/Masterminds/semver/v3 v3.2.0 // indirect
2225
github.com/davecgh/go-spew v1.1.1 // indirect
23-
github.com/golang/protobuf v1.5.2 // indirect
2426
github.com/google/uuid v1.3.0 // indirect
2527
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 // indirect
2628
github.com/huandu/xstrings v1.3.3 // indirect
2729
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 // indirect
2830
github.com/imdario/mergo v0.3.11 // indirect
2931
github.com/inconshreveable/mousetrap v1.0.1 // indirect
30-
github.com/invopop/jsonschema v0.7.0 // indirect
31-
github.com/linuxsuren/go-fake-runtime v0.0.0-20230413085645-15e77ab55dbd // indirect
3232
github.com/mitchellh/copystructure v1.0.0 // indirect
3333
github.com/mitchellh/reflectwalk v1.0.0 // indirect
3434
github.com/pmezard/go-difflib v1.0.0 // indirect
@@ -38,11 +38,12 @@ require (
3838
github.com/spf13/pflag v1.0.5 // indirect
3939
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
4040
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
41-
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
4241
golang.org/x/crypto v0.3.0 // indirect
4342
golang.org/x/net v0.8.0 // indirect
4443
golang.org/x/sys v0.6.0 // indirect
4544
golang.org/x/text v0.8.0 // indirect
4645
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
46+
google.golang.org/protobuf v1.30.0 // indirect
47+
gopkg.in/yaml.v2 v2.3.0 // indirect
4748
gopkg.in/yaml.v3 v3.0.1 // indirect
4849
)

go.sum

+2-1,058
Large diffs are not rendered by default.

pkg/testing/case.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ type Request struct {
3535

3636
// Response is the expected response
3737
type Response struct {
38-
StatusCode int `yaml:"statusCode" json:"bodyFromFile,omitempty"`
38+
StatusCode int `yaml:"statusCode" json:"statusCode,omitempty"`
3939
Body string `yaml:"body" json:"body,omitempty"`
4040
Header map[string]string `yaml:"header" json:"header,omitempty"`
4141
BodyFieldsExpect map[string]interface{} `yaml:"bodyFieldsExpect" json:"bodyFieldsExpect,omitempty"`

pkg/testing/parser.go

+20-1
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ import (
1010
"os"
1111
"strings"
1212

13+
"github.com/ghodss/yaml"
1314
"github.com/linuxsuren/api-testing/pkg/render"
1415
"github.com/linuxsuren/api-testing/pkg/util"
15-
"gopkg.in/yaml.v2"
16+
"github.com/linuxsuren/api-testing/sample"
17+
"github.com/xeipuuv/gojsonschema"
1618
)
1719

1820
// Parse parses a file and returns the test suite
@@ -21,6 +23,23 @@ func Parse(configFile string) (testSuite *TestSuite, err error) {
2123
if data, err = os.ReadFile(configFile); err == nil {
2224
testSuite, err = ParseFromData(data)
2325
}
26+
27+
// schema validation
28+
if err == nil {
29+
// convert YAML to JSON
30+
var jsonData []byte
31+
if jsonData, err = yaml.YAMLToJSON(data); err == nil {
32+
schemaLoader := gojsonschema.NewStringLoader(sample.Schema)
33+
documentLoader := gojsonschema.NewBytesLoader(jsonData)
34+
35+
var result *gojsonschema.Result
36+
if result, err = gojsonschema.Validate(schemaLoader, documentLoader); err == nil {
37+
if !result.Valid() {
38+
err = fmt.Errorf("%v", result.Errors())
39+
}
40+
}
41+
}
42+
}
2443
return
2544
}
2645

pkg/testing/parser_test.go

+3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ func TestParse(t *testing.T) {
3030
},
3131
}, suite.Items[0])
3232
}
33+
34+
_, err = Parse("testdata/invalid-testcase.yaml")
35+
assert.NotNil(t, err)
3336
}
3437

3538
func TestRequestRender(t *testing.T) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
name: projects
2+
request:
3+
api: https://foo
4+
expect:
5+
statuscode: 200

sample/api-testing-schema.json

-3
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,6 @@
7676
"type": "string"
7777
}
7878
},
79-
"required": [
80-
"statusCode"
81-
],
8279
"title": "Expect"
8380
},
8481
"Request": {

sample/constants.go

+3
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,6 @@ import _ "embed"
44

55
//go:embed testsuite-gitlab.yaml
66
var TestSuiteGitLab string
7+
8+
//go:embed api-testing-schema.json
9+
var Schema string

0 commit comments

Comments
 (0)