Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adjust XML output #1759

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 58 additions & 25 deletions pkg/claimhelper/claimhelper.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ import (
"encoding/xml"
"fmt"
"path/filepath"
"sort"
"strconv"
"strings"

"os"
"time"
Expand All @@ -41,7 +43,7 @@ const (
CNFFeatureValidationJunitXMLFileName = "validation_junit.xml"
CNFFeatureValidationReportKey = "cnf-feature-validation"
// dateTimeFormatDirective is the directive used to format date/time according to ISO 8601.
DateTimeFormatDirective = "2006-01-02T15:04:05+00:00"
DateTimeFormatDirective = "2006-01-02 15:04:05 -0700 MST"

// States for test cases
TestStateFailed = "failed"
Expand All @@ -60,33 +62,33 @@ type FailureMessage struct {
}

type TestCase struct {
Text string `xml:",chardata"`
Name string `xml:"name,attr"`
Classname string `xml:"classname,attr"`
Status string `xml:"status,attr"`
Time string `xml:"time,attr"`
SystemErr string `xml:"system-err,omitempty"`
Skipped SkippedMessage `xml:"skipped,omitempty"`
Failure FailureMessage `xml:"failure,omitempty"`
Text string `xml:",chardata"`
Name string `xml:"name,attr,omitempty"`
Classname string `xml:"classname,attr,omitempty"`
Status string `xml:"status,attr,omitempty"`
Time string `xml:"time,attr,omitempty"`
SystemErr string `xml:"system-err,omitempty"`
Skipped *SkippedMessage `xml:"skipped"`
Failure *FailureMessage `xml:"failure"`
}

type Testsuite struct {
Text string `xml:",chardata"`
Name string `xml:"name,attr"`
Package string `xml:"package,attr"`
Tests string `xml:"tests,attr"`
Disabled string `xml:"disabled,attr"`
Name string `xml:"name,attr,omitempty"`
Package string `xml:"package,attr,omitempty"`
Tests string `xml:"tests,attr,omitempty"`
Disabled string `xml:"disabled,attr,omitempty"`
Skipped string `xml:"skipped,attr,omitempty"`
Errors string `xml:"errors,attr,omitempty"`
Failures string `xml:"failures,attr,omitempty"`
Time string `xml:"time,attr"`
Timestamp string `xml:"timestamp,attr"`
Time string `xml:"time,attr,omitempty"`
Timestamp string `xml:"timestamp,attr,omitempty"`
Properties struct {
Text string `xml:",chardata"`
Property []struct {
Text string `xml:",chardata"`
Name string `xml:"name,attr"`
Value string `xml:"value,attr"`
Name string `xml:"name,attr,omitempty"`
Value string `xml:"value,attr,omitempty"`
} `xml:"property"`
} `xml:"properties"`
Testcase []TestCase `xml:"testcase"`
Expand All @@ -95,11 +97,11 @@ type Testsuite struct {
type TestSuitesXML struct {
XMLName xml.Name `xml:"testsuites"`
Text string `xml:",chardata"`
Tests string `xml:"tests,attr"`
Disabled string `xml:"disabled,attr"`
Tests string `xml:"tests,attr,omitempty"`
Disabled string `xml:"disabled,attr,omitempty"`
Errors string `xml:"errors,attr,omitempty"`
Failures string `xml:"failures,attr,omitempty"`
Time string `xml:"time,attr"`
Time string `xml:"time,attr,omitempty"`
Testsuite Testsuite `xml:"testsuite"`
}

Expand Down Expand Up @@ -153,6 +155,17 @@ func populateXMLFromClaim(c claim.Claim, startTime, endTime time.Time) TestSuite
const (
TestSuiteName = "CNF Certification Test Suite"
)

// Collector all of the Test IDs
allTestIDs := []string{}
for _, result := range c.Results {
typedResult := result.(claim.Result)
allTestIDs = append(allTestIDs, typedResult.TestID.Id)
}

// Sort the test IDs
sort.Strings(allTestIDs)

xmlOutput := TestSuitesXML{}
// <testsuites>
xmlOutput.Tests = strconv.Itoa(len(c.Results))
Expand All @@ -178,7 +191,7 @@ func populateXMLFromClaim(c claim.Claim, startTime, endTime time.Time) TestSuite
xmlOutput.Failures = strconv.Itoa(failedTests)
xmlOutput.Disabled = strconv.Itoa(skippedTests)
xmlOutput.Errors = strconv.Itoa(0)
xmlOutput.Time = strconv.FormatFloat(endTime.Sub(startTime).Seconds(), 'f', 3, 64)
xmlOutput.Time = strconv.FormatFloat(endTime.Sub(startTime).Seconds(), 'f', 5, 64)

// <testsuite>
xmlOutput.Testsuite.Name = TestSuiteName
Expand All @@ -188,30 +201,50 @@ func populateXMLFromClaim(c claim.Claim, startTime, endTime time.Time) TestSuite
xmlOutput.Testsuite.Skipped = strconv.Itoa(skippedTests)
xmlOutput.Testsuite.Errors = strconv.Itoa(0)

xmlOutput.Testsuite.Time = strconv.FormatFloat(endTime.Sub(startTime).Seconds(), 'f', 3, 64)
xmlOutput.Testsuite.Time = strconv.FormatFloat(endTime.Sub(startTime).Seconds(), 'f', 5, 64)
xmlOutput.Testsuite.Timestamp = time.Now().UTC().Format(DateTimeFormatDirective)

// <properties>

// <testcase>
for testID, result := range c.Results {
// Loop through all of the sorted test IDs
for _, testID := range allTestIDs {
// Type the result
typedResult := result.(claim.Result)
typedResult := c.Results[testID].(claim.Result)

testCase := TestCase{}
testCase.Name = testID
testCase.Classname = TestSuiteName
testCase.Status = typedResult.State
testCase.Time = strconv.FormatFloat(float64(typedResult.Duration), 'f', 3, 64)

// Clean the time strings to remove the " m=" suffix
start, err := time.Parse(DateTimeFormatDirective, strings.Split(typedResult.StartTime, " m=")[0])
if err != nil {
log.Error("Failed to parse start time: %v", err)
}
end, err := time.Parse(DateTimeFormatDirective, strings.Split(typedResult.EndTime, " m=")[0])
if err != nil {
log.Error("Failed to parse end time: %v", err)
}

// Calculate the duration of the test case
difference := end.Sub(start)
testCase.Time = strconv.FormatFloat(difference.Seconds(), 'f', 10, 64)

// Populate the skipped message if the test case was skipped
if testCase.Status == TestStateSkipped {
testCase.Skipped = &SkippedMessage{}
testCase.Skipped.Text = typedResult.SkipReason
} else {
testCase.Skipped = nil
}

// Populate the failure message if the test case failed
if testCase.Status == TestStateFailed {
testCase.Failure = &FailureMessage{}
testCase.Failure.Text = typedResult.CheckDetails
} else {
testCase.Failure = nil
}

// Append the test case to the test suite
Expand Down
15 changes: 7 additions & 8 deletions pkg/claimhelper/claimhelper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ func TestPopulateXMLFromClaim(t *testing.T) {
},
State: "failed",
SkipReason: failureMessage,
StartTime: "2023-12-20 14:51:33 -0600 MST",
EndTime: "2023-12-20 14:51:34 -0600 MST",
CheckDetails: "",
CapturedTestOutput: "test output",
CategoryClassification: &claim.CategoryClassification{
Expand All @@ -72,7 +74,7 @@ func TestPopulateXMLFromClaim(t *testing.T) {
Disabled: strconv.Itoa(0),
Tests: strconv.Itoa(1),
Errors: strconv.Itoa(0),
Time: strconv.Itoa(60),
Time: strconv.Itoa(1),
Testsuite: Testsuite{

Name: "test-suite1",
Expand All @@ -84,8 +86,8 @@ func TestPopulateXMLFromClaim(t *testing.T) {
Testcase: []TestCase{
{
Name: "test-case1",
Time: strconv.Itoa(60),
Failure: FailureMessage{
Time: strconv.Itoa(1),
Failure: &FailureMessage{
Message: "my custom failure message",
},
},
Expand All @@ -97,9 +99,9 @@ func TestPopulateXMLFromClaim(t *testing.T) {

for _, tc := range testCases {
// Build some 1 minute duration start and end time
startTime, err := time.Parse(DateTimeFormatDirective, "2006-01-02T15:04:05+00:00")
startTime, err := time.Parse(DateTimeFormatDirective, "2023-12-20 14:51:33 -0600 MST")
assert.Nil(t, err)
endTime, err := time.Parse(DateTimeFormatDirective, "2006-01-02T15:05:05+00:00")
endTime, err := time.Parse(DateTimeFormatDirective, "2023-12-20 14:51:34 -0600 MST")
assert.Nil(t, err)

xmlResult := populateXMLFromClaim(generateClaim(map[string]claim.Result{"test-case1": tc.testResult}), startTime, endTime)
Expand All @@ -108,9 +110,6 @@ func TestPopulateXMLFromClaim(t *testing.T) {
assert.Equal(t, tc.expectedXMLResult.Failures, xmlResult.Failures)
assert.Equal(t, tc.expectedXMLResult.Tests, xmlResult.Tests)
assert.Equal(t, tc.expectedXMLResult.Errors, xmlResult.Errors)
assert.Equal(t, tc.expectedXMLResult.Testsuite.Skipped, xmlResult.Testsuite.Skipped)

// convert "60.000" string to 60 int
expectedTimeFloat, err := strconv.ParseFloat(tc.expectedXMLResult.Time, 32)
assert.Nil(t, err)
actualTimeFloat, err := strconv.ParseFloat(xmlResult.Time, 32)
Expand Down
17 changes: 17 additions & 0 deletions pkg/flags/flags_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (C) 2020-2023 Red Hat, Inc.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

package flags
Loading