mirror of
https://github.com/yannh/kubeconform.git
synced 2026-02-11 14:09:21 +00:00
173 lines
4.2 KiB
Go
173 lines
4.2 KiB
Go
package output
|
|
|
|
import (
|
|
"bytes"
|
|
"github.com/yannh/kubeconform/pkg/resource"
|
|
"regexp"
|
|
"testing"
|
|
|
|
"github.com/yannh/kubeconform/pkg/validator"
|
|
|
|
"github.com/beevik/etree"
|
|
)
|
|
|
|
func isNumeric(s string) bool {
|
|
matched, _ := regexp.MatchString("^\\d+(\\.\\d+)?$", s)
|
|
return matched
|
|
}
|
|
|
|
func TestJUnitWrite(t *testing.T) {
|
|
for _, testCase := range []struct {
|
|
name string
|
|
withSummary bool
|
|
isStdin bool
|
|
verbose bool
|
|
results []validator.Result
|
|
evaluate func(d *etree.Document)
|
|
}{
|
|
{
|
|
"empty document",
|
|
false,
|
|
false,
|
|
false,
|
|
[]validator.Result{},
|
|
func(d *etree.Document) {
|
|
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",
|
|
true,
|
|
false,
|
|
true,
|
|
[]validator.Result{
|
|
{
|
|
Resource: resource.Resource{
|
|
Path: "deployment.yml",
|
|
Bytes: []byte(`apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: "my-app"
|
|
namespace: "my-namespace"
|
|
`),
|
|
},
|
|
Status: validator.Valid,
|
|
Err: nil,
|
|
},
|
|
},
|
|
func(d *etree.Document) {
|
|
suites := d.FindElements("//testsuites/testsuite")
|
|
if len(suites) != 1 {
|
|
t.Errorf("Expected exactly 1 testsuite element, got %d", len(suites))
|
|
return
|
|
}
|
|
suite := suites[0]
|
|
for _, attr := range suite.Attr {
|
|
switch attr.Key {
|
|
case "name":
|
|
if attr.Value != "deployment.yml" {
|
|
t.Errorf("Test suite name should be the resource path")
|
|
}
|
|
continue
|
|
case "id":
|
|
if attr.Value != "1" {
|
|
t.Errorf("testsuite/@id should be 1")
|
|
}
|
|
continue
|
|
case "tests":
|
|
if attr.Value != "1" {
|
|
t.Errorf("testsuite/@tests should be 1")
|
|
}
|
|
continue
|
|
case "failures":
|
|
if attr.Value != "0" {
|
|
t.Errorf("testsuite/@failures should be 0")
|
|
}
|
|
continue
|
|
case "errors":
|
|
if attr.Value != "0" {
|
|
t.Errorf("testsuite/@errors should be 0")
|
|
}
|
|
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")
|
|
}
|
|
},
|
|
},
|
|
} {
|
|
w := new(bytes.Buffer)
|
|
o := junitOutput(w, testCase.withSummary, testCase.isStdin, testCase.verbose)
|
|
|
|
for _, res := range testCase.results {
|
|
o.Write(res)
|
|
}
|
|
o.Flush()
|
|
|
|
doc := etree.NewDocument()
|
|
doc.ReadFromString(w.String())
|
|
|
|
testCase.evaluate(doc)
|
|
}
|
|
}
|