mirror of
https://github.com/yannh/kubeconform.git
synced 2026-02-21 02:47:01 +00:00
Update Junit tests, fix #45
This commit is contained in:
parent
1b01a42488
commit
2eefa7fc22
5 changed files with 72 additions and 141 deletions
|
|
@ -10,9 +10,10 @@ import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/yannh/kubeconform/pkg/validator"
|
|
||||||
"io"
|
"io"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/yannh/kubeconform/pkg/validator"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TestSuiteCollection struct {
|
type TestSuiteCollection struct {
|
||||||
|
|
@ -105,8 +106,6 @@ func (o *junito) Write(result validator.Result) error {
|
||||||
o.suites[result.Resource.Path] = suite
|
o.suites[result.Resource.Path] = suite
|
||||||
}
|
}
|
||||||
|
|
||||||
suite.Tests++
|
|
||||||
|
|
||||||
sig, _ := result.Resource.Signature()
|
sig, _ := result.Resource.Signature()
|
||||||
var objectName string
|
var objectName string
|
||||||
if len(sig.Namespace) > 0 {
|
if len(sig.Namespace) > 0 {
|
||||||
|
|
@ -121,21 +120,20 @@ func (o *junito) Write(result validator.Result) error {
|
||||||
case validator.Valid:
|
case validator.Valid:
|
||||||
o.nValid++
|
o.nValid++
|
||||||
case validator.Invalid:
|
case validator.Invalid:
|
||||||
suite.Failures++
|
|
||||||
o.nInvalid++
|
o.nInvalid++
|
||||||
failure := TestCaseError{Message: result.Err.Error()}
|
failure := TestCaseError{Message: result.Err.Error()}
|
||||||
testCase.Failure = append(testCase.Failure, failure)
|
testCase.Failure = append(testCase.Failure, failure)
|
||||||
case validator.Error:
|
case validator.Error:
|
||||||
suite.Errors++
|
|
||||||
o.nErrors++
|
o.nErrors++
|
||||||
testCase.Error = &TestCaseError{Message: result.Err.Error()}
|
testCase.Error = &TestCaseError{Message: result.Err.Error()}
|
||||||
case validator.Skipped:
|
case validator.Skipped:
|
||||||
suite.Skipped++
|
|
||||||
testCase.Skipped = &TestCaseSkipped{}
|
testCase.Skipped = &TestCaseSkipped{}
|
||||||
o.nSkipped++
|
o.nSkipped++
|
||||||
case validator.Empty:
|
case validator.Empty:
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suite.Tests++
|
||||||
suite.Cases = append(suite.Cases, testCase)
|
suite.Cases = append(suite.Cases, testCase)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -2,73 +2,36 @@ package output
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"github.com/yannh/kubeconform/pkg/resource"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/yannh/kubeconform/pkg/validator"
|
"github.com/yannh/kubeconform/pkg/resource"
|
||||||
|
|
||||||
"github.com/beevik/etree"
|
"github.com/yannh/kubeconform/pkg/validator"
|
||||||
)
|
)
|
||||||
|
|
||||||
func isNumeric(s string) bool {
|
func TestJunitWrite(t *testing.T) {
|
||||||
matched, _ := regexp.MatchString("^\\d+(\\.\\d+)?$", s)
|
|
||||||
return matched
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestJUnitWrite(t *testing.T) {
|
|
||||||
for _, testCase := range []struct {
|
for _, testCase := range []struct {
|
||||||
name string
|
name string
|
||||||
withSummary bool
|
withSummary bool
|
||||||
isStdin bool
|
isStdin bool
|
||||||
verbose bool
|
verbose bool
|
||||||
results []validator.Result
|
results []validator.Result
|
||||||
evaluate func(d *etree.Document)
|
expect string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
"empty document",
|
"an empty result",
|
||||||
false,
|
true,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
[]validator.Result{},
|
[]validator.Result{},
|
||||||
func(d *etree.Document) {
|
"<testsuites name=\"kubeconform\" time=\"\" tests=\"0\" failures=\"0\" disabled=\"0\" errors=\"0\"></testsuites>\n",
|
||||||
root := d.FindElement("/testsuites")
|
|
||||||
if root == nil {
|
|
||||||
t.Errorf("Can't find root testsuite element")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, attr := range root.Attr {
|
|
||||||
switch attr.Key {
|
|
||||||
case "time":
|
|
||||||
case "tests":
|
|
||||||
case "failures":
|
|
||||||
case "disabled":
|
|
||||||
case "errors":
|
|
||||||
if !isNumeric(attr.Value) {
|
|
||||||
t.Errorf("Expected a number for /testsuites/@%s", attr.Key)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
case "name":
|
|
||||||
if attr.Value != "kubeconform" {
|
|
||||||
t.Errorf("Expected 'kubeconform' for /testsuites/@name")
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
default:
|
|
||||||
t.Errorf("Unknown attribute /testsuites/@%s", attr.Key)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
suites := root.SelectElements("testsuite")
|
|
||||||
if len(suites) != 0 {
|
|
||||||
t.Errorf("No testsuite elements should be generated when there are no resources")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"a single deployment, verbose, with summary",
|
"a single deployment, summary, no verbose",
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
true,
|
false,
|
||||||
[]validator.Result{
|
[]validator.Result{
|
||||||
{
|
{
|
||||||
Resource: resource.Resource{
|
Resource: resource.Resource{
|
||||||
|
|
@ -77,84 +40,52 @@ func TestJUnitWrite(t *testing.T) {
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: "my-app"
|
name: "my-app"
|
||||||
namespace: "my-namespace"
|
|
||||||
`),
|
`),
|
||||||
},
|
},
|
||||||
Status: validator.Valid,
|
Status: validator.Valid,
|
||||||
Err: nil,
|
Err: nil,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
func(d *etree.Document) {
|
"<testsuites name=\"kubeconform\" time=\"\" tests=\"1\" failures=\"0\" disabled=\"0\" errors=\"0\">\n" +
|
||||||
suites := d.FindElements("//testsuites/testsuite")
|
" <testsuite name=\"deployment.yml\" id=\"1\" tests=\"1\" failures=\"0\" errors=\"0\" disabled=\"0\" skipped=\"0\">\n" +
|
||||||
if len(suites) != 1 {
|
" <properties></properties>\n" +
|
||||||
t.Errorf("Expected exactly 1 testsuite element, got %d", len(suites))
|
" <testcase name=\"my-app\" classname=\"Deployment@apps/v1\"></testcase>\n" +
|
||||||
return
|
" </testsuite>\n" +
|
||||||
}
|
"</testsuites>\n",
|
||||||
suite := suites[0]
|
},
|
||||||
for _, attr := range suite.Attr {
|
{
|
||||||
switch attr.Key {
|
"a deployment, an empty resource, summary, no verbose",
|
||||||
case "name":
|
true,
|
||||||
if attr.Value != "deployment.yml" {
|
false,
|
||||||
t.Errorf("Test suite name should be the resource path")
|
false,
|
||||||
}
|
[]validator.Result{
|
||||||
continue
|
{
|
||||||
case "id":
|
Resource: resource.Resource{
|
||||||
if attr.Value != "1" {
|
Path: "deployment.yml",
|
||||||
t.Errorf("testsuite/@id should be 1")
|
Bytes: []byte(`apiVersion: apps/v1
|
||||||
}
|
kind: Deployment
|
||||||
continue
|
metadata:
|
||||||
case "tests":
|
name: "my-app"
|
||||||
if attr.Value != "1" {
|
`),
|
||||||
t.Errorf("testsuite/@tests should be 1")
|
},
|
||||||
}
|
Status: validator.Valid,
|
||||||
continue
|
Err: nil,
|
||||||
case "failures":
|
},
|
||||||
if attr.Value != "0" {
|
{
|
||||||
t.Errorf("testsuite/@failures should be 0")
|
Resource: resource.Resource{
|
||||||
}
|
Path: "deployment.yml",
|
||||||
continue
|
Bytes: []byte(`#A single comment`),
|
||||||
case "errors":
|
},
|
||||||
if attr.Value != "0" {
|
Status: validator.Empty,
|
||||||
t.Errorf("testsuite/@errors should be 0")
|
Err: nil,
|
||||||
}
|
},
|
||||||
continue
|
|
||||||
case "disabled":
|
|
||||||
if attr.Value != "0" {
|
|
||||||
t.Errorf("testsuite/@disabled should be 0")
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
case "skipped":
|
|
||||||
if attr.Value != "0" {
|
|
||||||
t.Errorf("testsuite/@skipped should be 0")
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
default:
|
|
||||||
t.Errorf("Unknown testsuite attribute %s", attr.Key)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
testcases := suite.SelectElements("testcase")
|
|
||||||
if len(testcases) != 1 {
|
|
||||||
t.Errorf("Expected exactly 1 testcase, got %d", len(testcases))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
testcase := testcases[0]
|
|
||||||
if testcase.SelectAttrValue("name", "") != "my-namespace/my-app" {
|
|
||||||
t.Errorf("Test case name should be namespace / name")
|
|
||||||
}
|
|
||||||
if testcase.SelectAttrValue("classname", "") != "Deployment@apps/v1" {
|
|
||||||
t.Errorf("Test case class name should be resource kind @ api version")
|
|
||||||
}
|
|
||||||
if testcase.SelectElement("skipped") != nil {
|
|
||||||
t.Errorf("skipped element should not be generated if the kind was not skipped")
|
|
||||||
}
|
|
||||||
if testcase.SelectElement("error") != nil {
|
|
||||||
t.Errorf("error element should not be generated if there was no error")
|
|
||||||
}
|
|
||||||
if len(testcase.SelectElements("failure")) != 0 {
|
|
||||||
t.Errorf("failure elements should not be generated if there were no failures")
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
"<testsuites name=\"kubeconform\" time=\"\" tests=\"1\" failures=\"0\" disabled=\"0\" errors=\"0\">\n" +
|
||||||
|
" <testsuite name=\"deployment.yml\" id=\"1\" tests=\"1\" failures=\"0\" errors=\"0\" disabled=\"0\" skipped=\"0\">\n" +
|
||||||
|
" <properties></properties>\n" +
|
||||||
|
" <testcase name=\"my-app\" classname=\"Deployment@apps/v1\"></testcase>\n" +
|
||||||
|
" </testsuite>\n" +
|
||||||
|
"</testsuites>\n",
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
w := new(bytes.Buffer)
|
w := new(bytes.Buffer)
|
||||||
|
|
@ -165,9 +96,13 @@ metadata:
|
||||||
}
|
}
|
||||||
o.Flush()
|
o.Flush()
|
||||||
|
|
||||||
doc := etree.NewDocument()
|
// We remove the time, which will be different every time, before the comparison
|
||||||
doc.ReadFromString(w.String())
|
output := w.String()
|
||||||
|
r := regexp.MustCompile(`time="[^"]*"`)
|
||||||
|
output = r.ReplaceAllString(output, "time=\"\"")
|
||||||
|
|
||||||
testCase.evaluate(doc)
|
if output != testCase.expect {
|
||||||
|
t.Errorf("%s - expected:, got:\n%s\n%s", testCase.name, testCase.expect, output)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"github.com/yannh/kubeconform/pkg/validator"
|
"github.com/yannh/kubeconform/pkg/validator"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestTextWrite(t *testing.T) {
|
func TestTapWrite(t *testing.T) {
|
||||||
for _, testCase := range []struct {
|
for _, testCase := range []struct {
|
||||||
name string
|
name string
|
||||||
withSummary bool
|
withSummary bool
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"github.com/yannh/kubeconform/pkg/validator"
|
"github.com/yannh/kubeconform/pkg/validator"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestTapWrite(t *testing.T) {
|
func TestTextWrite(t *testing.T) {
|
||||||
for _, testCase := range []struct {
|
for _, testCase := range []struct {
|
||||||
name string
|
name string
|
||||||
withSummary bool
|
withSummary bool
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,12 @@
|
||||||
package validator
|
package validator
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/yannh/kubeconform/pkg/registry"
|
"github.com/yannh/kubeconform/pkg/registry"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/yannh/kubeconform/pkg/resource"
|
"github.com/yannh/kubeconform/pkg/resource"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
type mockRegistry struct {
|
type mockRegistry struct {
|
||||||
SchemaDownloader func() ([]byte, error)
|
SchemaDownloader func() ([]byte, error)
|
||||||
}
|
}
|
||||||
|
|
@ -22,14 +21,13 @@ func (m mockRegistry) DownloadSchema(resourceKind, resourceAPIVersion, k8sVersio
|
||||||
return m.SchemaDownloader()
|
return m.SchemaDownloader()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func TestValidate(t *testing.T) {
|
func TestValidate(t *testing.T) {
|
||||||
for i, testCase := range []struct {
|
for i, testCase := range []struct {
|
||||||
name string
|
name string
|
||||||
rawResource, schemaRegistry1 []byte
|
rawResource, schemaRegistry1 []byte
|
||||||
schemaRegistry2 []byte
|
schemaRegistry2 []byte
|
||||||
ignoreMissingSchema bool
|
ignoreMissingSchema bool
|
||||||
expect Status
|
expect Status
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
"valid resource",
|
"valid resource",
|
||||||
|
|
@ -292,11 +290,11 @@ lastName: bar
|
||||||
} {
|
} {
|
||||||
val := v{
|
val := v{
|
||||||
opts: Opts{
|
opts: Opts{
|
||||||
SkipKinds: map[string]struct{}{},
|
SkipKinds: map[string]struct{}{},
|
||||||
RejectKinds: map[string]struct{}{},
|
RejectKinds: map[string]struct{}{},
|
||||||
IgnoreMissingSchemas: testCase.ignoreMissingSchema,
|
IgnoreMissingSchemas: testCase.ignoreMissingSchema,
|
||||||
},
|
},
|
||||||
schemaCache: nil,
|
schemaCache: nil,
|
||||||
schemaDownload: downloadSchema,
|
schemaDownload: downloadSchema,
|
||||||
regs: []registry.Registry{
|
regs: []registry.Registry{
|
||||||
newMockRegistry(func() ([]byte, error) {
|
newMockRegistry(func() ([]byte, error) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue