github.com/munnerz/test-infra@v0.0.0-20190108210205-ce3d181dc989/gopherage/pkg/cov/junit/xmlwriter.go (about) 1 /* 2 Copyright 2018 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 // Package takes coverage profile file as input and produces junit xml that is consumable by TestGrid 18 19 package junit 20 21 import ( 22 "encoding/xml" 23 "fmt" 24 25 "golang.org/x/tools/cover" 26 27 "k8s.io/test-infra/gopherage/pkg/cov/junit/calculation" 28 ) 29 30 // Property defines the xml element that stores the value of code coverage 31 type Property struct { 32 Name string `xml:"name,attr"` 33 Value string `xml:"value,attr"` 34 } 35 36 // Properties defines the xml element that stores the a list of properties that associated with one testcase 37 type Properties struct { 38 PropertyList []Property `xml:"property"` 39 } 40 41 // TestCase defines the xml element that stores all information associated with one test case 42 type TestCase struct { 43 ClassName string `xml:"class_name,attr"` 44 Name string `xml:"name,attr"` 45 Time string `xml:"time,attr"` 46 Failure bool `xml:"failure,omitempty"` 47 PropertyList Properties `xml:"properties"` 48 } 49 50 // Testsuite defines the outer-most xml element that contains all test cases 51 type Testsuite struct { 52 XMLName string `xml:"testsuite"` 53 Testcases []TestCase `xml:"testcase"` 54 } 55 56 func (ts *Testsuite) addTestCase(coverageTargetName string, ratio, threshold float32) { 57 testCase := TestCase{ 58 ClassName: "go_coverage", 59 Name: coverageTargetName, 60 Time: "0", 61 Failure: ratio < threshold, 62 PropertyList: Properties{ 63 PropertyList: []Property{ 64 { 65 Name: "coverage", 66 Value: fmt.Sprintf("%.1f", ratio*100), 67 }, 68 }, 69 }, 70 } 71 ts.Testcases = append(ts.Testcases, testCase) 72 } 73 74 // toTestsuite populates Testsuite struct with data from CoverageList and actual file 75 // directories from OS 76 func toTestsuite(covList *calculation.CoverageList, coverageThreshold float32) Testsuite { 77 ts := Testsuite{} 78 ts.addTestCase("OVERALL", covList.Ratio(), coverageThreshold) 79 80 for _, cov := range covList.Group { 81 ts.addTestCase(cov.Name, cov.Ratio(), coverageThreshold) 82 } 83 84 for _, dir := range covList.ListDirectories() { 85 dirCov := covList.Subset(dir) 86 ts.addTestCase(dir, dirCov.Ratio(), coverageThreshold) 87 } 88 return ts 89 } 90 91 // ProfileToTestsuiteXML uses coverage profile to produce junit xml 92 // which serves as the input for test coverage testgrid 93 func ProfileToTestsuiteXML(profiles []*cover.Profile, coverageThreshold float32) ([]byte, error) { 94 covList := calculation.ProduceCovList(profiles) 95 96 ts := toTestsuite(covList, coverageThreshold) 97 return xml.MarshalIndent(ts, "", " ") 98 }