feat: support to validate the YAML file via schema (#49)
This commit is contained in:
parent
49441573e8
commit
45a4d5166a
10
cmd/root.go
10
cmd/root.go
|
@ -22,3 +22,13 @@ func NewRootCmd(execer fakeruntime.Execer, gRPCServer gRPCServer) (c *cobra.Comm
|
||||||
createServiceCommand(execer))
|
createServiceCommand(execer))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type printer interface {
|
||||||
|
Println(i ...interface{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func println(printer printer, err error, i ...interface{}) {
|
||||||
|
if err != nil {
|
||||||
|
printer.Println(i...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
12
cmd/run.go
12
cmd/run.go
|
@ -114,13 +114,13 @@ func (o *runOption) runE(cmd *cobra.Command, args []string) (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// print the report
|
// print the report
|
||||||
if results, reportErr := o.reporter.ExportAllReportResults(); reportErr == nil {
|
var reportErr error
|
||||||
if reportErr = o.reportWriter.Output(results); reportErr != nil {
|
var results runner.ReportResultSlice
|
||||||
cmd.Println("failed to Output all reports", reportErr)
|
if results, reportErr = o.reporter.ExportAllReportResults(); reportErr == nil {
|
||||||
}
|
outputErr := o.reportWriter.Output(results)
|
||||||
} else {
|
println(cmd, outputErr, "failed to Output all reports", outputErr)
|
||||||
cmd.Println("failed to export all reports", reportErr)
|
|
||||||
}
|
}
|
||||||
|
println(cmd, reportErr, "failed to export all reports", reportErr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
@ -175,5 +177,17 @@ func TestPreRunE(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPrinter(t *testing.T) {
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
c := &cobra.Command{}
|
||||||
|
c.SetOutput(buf)
|
||||||
|
|
||||||
|
println(c, nil, "foo")
|
||||||
|
assert.Empty(t, buf.String())
|
||||||
|
|
||||||
|
println(c, errors.New("bar"), "foo")
|
||||||
|
assert.Equal(t, "foo\n", buf.String())
|
||||||
|
}
|
||||||
|
|
||||||
const urlFoo = "http://foo"
|
const urlFoo = "http://foo"
|
||||||
const simpleSuite = "testdata/simple-suite.yaml"
|
const simpleSuite = "testdata/simple-suite.yaml"
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
name: Simple
|
name: Simple
|
||||||
api: http://foo/
|
api: http://foo
|
||||||
items:
|
items:
|
||||||
- request:
|
- request:
|
||||||
api: /bar
|
api: /bar
|
||||||
|
name: bar
|
||||||
|
|
13
go.mod
13
go.mod
|
@ -6,29 +6,29 @@ require (
|
||||||
github.com/Masterminds/sprig/v3 v3.2.3
|
github.com/Masterminds/sprig/v3 v3.2.3
|
||||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883
|
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883
|
||||||
github.com/antonmedv/expr v1.12.1
|
github.com/antonmedv/expr v1.12.1
|
||||||
|
github.com/ghodss/yaml v1.0.0
|
||||||
|
github.com/golang/protobuf v1.5.2
|
||||||
github.com/h2non/gock v1.2.0
|
github.com/h2non/gock v1.2.0
|
||||||
|
github.com/invopop/jsonschema v0.7.0
|
||||||
|
github.com/linuxsuren/go-fake-runtime v0.0.0-20230413085645-15e77ab55dbd
|
||||||
github.com/linuxsuren/unstructured v0.0.1
|
github.com/linuxsuren/unstructured v0.0.1
|
||||||
github.com/spf13/cobra v1.6.1
|
github.com/spf13/cobra v1.6.1
|
||||||
github.com/stretchr/testify v1.8.2
|
github.com/stretchr/testify v1.8.2
|
||||||
|
github.com/xeipuuv/gojsonschema v1.2.0
|
||||||
golang.org/x/sync v0.1.0
|
golang.org/x/sync v0.1.0
|
||||||
google.golang.org/grpc v1.54.0
|
google.golang.org/grpc v1.54.0
|
||||||
google.golang.org/protobuf v1.30.0
|
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||||
github.com/Masterminds/semver/v3 v3.2.0 // indirect
|
github.com/Masterminds/semver/v3 v3.2.0 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/golang/protobuf v1.5.2 // indirect
|
|
||||||
github.com/google/uuid v1.3.0 // indirect
|
github.com/google/uuid v1.3.0 // indirect
|
||||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 // indirect
|
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 // indirect
|
||||||
github.com/huandu/xstrings v1.3.3 // indirect
|
github.com/huandu/xstrings v1.3.3 // indirect
|
||||||
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 // indirect
|
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 // indirect
|
||||||
github.com/imdario/mergo v0.3.11 // indirect
|
github.com/imdario/mergo v0.3.11 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.0.1 // indirect
|
github.com/inconshreveable/mousetrap v1.0.1 // indirect
|
||||||
github.com/invopop/jsonschema v0.7.0 // indirect
|
|
||||||
github.com/linuxsuren/go-fake-runtime v0.0.0-20230413085645-15e77ab55dbd // indirect
|
|
||||||
github.com/mitchellh/copystructure v1.0.0 // indirect
|
github.com/mitchellh/copystructure v1.0.0 // indirect
|
||||||
github.com/mitchellh/reflectwalk v1.0.0 // indirect
|
github.com/mitchellh/reflectwalk v1.0.0 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
@ -38,11 +38,12 @@ require (
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
|
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
|
||||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||||
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
|
|
||||||
golang.org/x/crypto v0.3.0 // indirect
|
golang.org/x/crypto v0.3.0 // indirect
|
||||||
golang.org/x/net v0.8.0 // indirect
|
golang.org/x/net v0.8.0 // indirect
|
||||||
golang.org/x/sys v0.6.0 // indirect
|
golang.org/x/sys v0.6.0 // indirect
|
||||||
golang.org/x/text v0.8.0 // indirect
|
golang.org/x/text v0.8.0 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
|
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
|
||||||
|
google.golang.org/protobuf v1.30.0 // indirect
|
||||||
|
gopkg.in/yaml.v2 v2.3.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|
|
@ -35,7 +35,7 @@ type Request struct {
|
||||||
|
|
||||||
// Response is the expected response
|
// Response is the expected response
|
||||||
type Response struct {
|
type Response struct {
|
||||||
StatusCode int `yaml:"statusCode" json:"bodyFromFile,omitempty"`
|
StatusCode int `yaml:"statusCode" json:"statusCode,omitempty"`
|
||||||
Body string `yaml:"body" json:"body,omitempty"`
|
Body string `yaml:"body" json:"body,omitempty"`
|
||||||
Header map[string]string `yaml:"header" json:"header,omitempty"`
|
Header map[string]string `yaml:"header" json:"header,omitempty"`
|
||||||
BodyFieldsExpect map[string]interface{} `yaml:"bodyFieldsExpect" json:"bodyFieldsExpect,omitempty"`
|
BodyFieldsExpect map[string]interface{} `yaml:"bodyFieldsExpect" json:"bodyFieldsExpect,omitempty"`
|
||||||
|
|
|
@ -10,9 +10,11 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ghodss/yaml"
|
||||||
"github.com/linuxsuren/api-testing/pkg/render"
|
"github.com/linuxsuren/api-testing/pkg/render"
|
||||||
"github.com/linuxsuren/api-testing/pkg/util"
|
"github.com/linuxsuren/api-testing/pkg/util"
|
||||||
"gopkg.in/yaml.v2"
|
"github.com/linuxsuren/api-testing/sample"
|
||||||
|
"github.com/xeipuuv/gojsonschema"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Parse parses a file and returns the test suite
|
// Parse parses a file and returns the test suite
|
||||||
|
@ -21,6 +23,23 @@ func Parse(configFile string) (testSuite *TestSuite, err error) {
|
||||||
if data, err = os.ReadFile(configFile); err == nil {
|
if data, err = os.ReadFile(configFile); err == nil {
|
||||||
testSuite, err = ParseFromData(data)
|
testSuite, err = ParseFromData(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// schema validation
|
||||||
|
if err == nil {
|
||||||
|
// convert YAML to JSON
|
||||||
|
var jsonData []byte
|
||||||
|
if jsonData, err = yaml.YAMLToJSON(data); err == nil {
|
||||||
|
schemaLoader := gojsonschema.NewStringLoader(sample.Schema)
|
||||||
|
documentLoader := gojsonschema.NewBytesLoader(jsonData)
|
||||||
|
|
||||||
|
var result *gojsonschema.Result
|
||||||
|
if result, err = gojsonschema.Validate(schemaLoader, documentLoader); err == nil {
|
||||||
|
if !result.Valid() {
|
||||||
|
err = fmt.Errorf("%v", result.Errors())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,9 @@ func TestParse(t *testing.T) {
|
||||||
},
|
},
|
||||||
}, suite.Items[0])
|
}, suite.Items[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_, err = Parse("testdata/invalid-testcase.yaml")
|
||||||
|
assert.NotNil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRequestRender(t *testing.T) {
|
func TestRequestRender(t *testing.T) {
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
name: projects
|
||||||
|
request:
|
||||||
|
api: https://foo
|
||||||
|
expect:
|
||||||
|
statuscode: 200
|
|
@ -76,9 +76,6 @@
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
|
||||||
"statusCode"
|
|
||||||
],
|
|
||||||
"title": "Expect"
|
"title": "Expect"
|
||||||
},
|
},
|
||||||
"Request": {
|
"Request": {
|
||||||
|
|
|
@ -4,3 +4,6 @@ import _ "embed"
|
||||||
|
|
||||||
//go:embed testsuite-gitlab.yaml
|
//go:embed testsuite-gitlab.yaml
|
||||||
var TestSuiteGitLab string
|
var TestSuiteGitLab string
|
||||||
|
|
||||||
|
//go:embed api-testing-schema.json
|
||||||
|
var Schema string
|
||||||
|
|
Loading…
Reference in New Issue