Update Junit tests, fix #45

This commit is contained in:
Yann Hamon 2021-08-29 12:57:25 +02:00
parent 1b01a42488
commit 2eefa7fc22
5 changed files with 72 additions and 141 deletions

View file

@ -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

View file

@ -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)
}
} }
} }

View file

@ -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

View file

@ -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

View file

@ -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) {