Skip to content
Permalink
Browse files

Add xccov support (#399)

  • Loading branch information...
ale7714 committed Jul 31, 2019
1 parent eebc436 commit 3ee4f719b3f3b7b22ff308c06e2fe2c5685e7fde
@@ -17,6 +17,7 @@ import (
"github.com/codeclimate/test-reporter/formatters/jacoco"
"github.com/codeclimate/test-reporter/formatters/lcov"
"github.com/codeclimate/test-reporter/formatters/simplecov"
"github.com/codeclimate/test-reporter/formatters/xccov"
"github.com/gobuffalo/envy"
"github.com/pkg/errors"
"github.com/spf13/cobra"
@@ -35,7 +36,7 @@ type CoverageFormatter struct {
var formatOptions = CoverageFormatter{}

// a prioritized list of the formatters to use
var formatterList = []string{"clover", "cobertura", "coverage.py", "excoveralls", "gcov", "gocov", "jacoco", "lcov", "simplecov"}
var formatterList = []string{"clover", "cobertura", "coverage.py", "excoveralls", "gcov", "gocov", "jacoco", "lcov", "simplecov", "xccov"}

// a map of the formatters to use
var formatterMap = map[string]formatters.Formatter{
@@ -48,6 +49,7 @@ var formatterMap = map[string]formatters.Formatter{
"jacoco": &jacoco.Formatter{},
"lcov": &lcov.Formatter{},
"simplecov": &simplecov.Formatter{},
"xccov": &xccov.Formatter{},
}

// formatCoverageCmd represents the format command
@@ -0,0 +1,16 @@
package xccov

type sourceFile struct {
Path string `json:"path"`
Functions []struct {
CoveredLines int `json:"coveredLines"`
LineNumber int `json:"lineNumber"`
ExecutableLines int `json:"executableLines"`
} `json:"functions"`
}

type xccovFile struct {
Targets []struct {
Files []sourceFile `json:"files"`
} `json:"targets"`
}
@@ -0,0 +1,88 @@
package xccov

import (
"encoding/json"
"os"
"strings"

"github.com/Sirupsen/logrus"
"github.com/codeclimate/test-reporter/env"
"github.com/codeclimate/test-reporter/formatters"
"github.com/pkg/errors"
)

var searchPaths = []string{"coverage.json"}

type Formatter struct {
Path string
}

func (f *Formatter) Search(paths ...string) (string, error) {
paths = append(paths, searchPaths...)
for _, p := range paths {
logrus.Debugf("checking search path %s for xccov formatter", p)
if _, err := os.Stat(p); err == nil {
f.Path = p
return p, nil
}
}

return "", errors.WithStack(errors.Errorf("could not find any files in search paths for xccov. search paths were: %s", strings.Join(paths, ", ")))
}

func (r Formatter) Format() (formatters.Report, error) {
report, err := formatters.NewReport()
if err != nil {
return report, err
}

inputXccovFile, err := os.Open(r.Path)
if err != nil {
return report, errors.WithStack(errors.Errorf("could not open coverage file %s", r.Path))
}

covFile := &xccovFile{}
err = json.NewDecoder(inputXccovFile).Decode(&covFile)
if err != nil {
return report, errors.WithStack(err)
}

gitHead, _ := env.GetHead()
for _, target := range covFile.Targets {
for _, jsonFile := range target.Files {
num := 1
sourceFile, err := formatters.NewSourceFile(jsonFile.Path, gitHead)
if err != nil {
logrus.Warnf("Couldn't find file for path \"%s\" from %s coverage data. Ignore if the path doesn't correspond to an existent file in your repo.", jsonFile.Path, r.Path)
continue
}

for _, function := range jsonFile.Functions {
// fill non executable lines will null
for num < function.LineNumber {
sourceFile.Coverage = append(sourceFile.Coverage, formatters.NullInt{})
num++
}
// fill covered lines with 1
for i := 0; i < function.CoveredLines; i++ {
sourceFile.Coverage = append(sourceFile.Coverage, formatters.NewNullInt(1))
num++
}
// fill non-covered but executable lines with 0
nonExecutableLines := function.ExecutableLines - function.CoveredLines
for i := 0; i < nonExecutableLines; i++ {
sourceFile.Coverage = append(sourceFile.Coverage, formatters.NewNullInt(0))
num++
}
}

err = report.AddSourceFile(sourceFile)
if err != nil {
return report, errors.WithStack(err)
}
}
}


return report, nil
}
@@ -0,0 +1,87 @@
{
"coveredLines": 27,
"lineCoverage": 0.20930232558,
"errors": [
{
"code": 0,
"localizedDescription": "Failed to generate coverage for target 'Pods_SuperAppTests.framework' at path \/Library\/Developer\/Xcode\/DerivedData\/SuperApp-enbcwwvvobzujubcgbepwgrjngiy\/Build\/Products\/Debug-iphonesimulator\/Pods_SuperAppTests.framework\/Pods_SuperAppTests: Malformed coverage data",
"domain": "IDECoverageReportGenerationErrorDomain"
},
{
"code": 0,
"localizedDescription": "Failed to generate coverage for target 'Pods_SuperAppSiri.framework' at path \/Library\/Developer\/Xcode\/DerivedData\/SuperApp-enbcwwvvobzujubcgbepwgrjngiy\/Build\/Products\/Debug-iphonesimulator\/Pods_SuperAppSiri.framework\/Pods_SuperAppSiri: Malformed coverage data",
"domain": "IDECoverageReportGenerationErrorDomain"
}
],
"targets": [
{
"coveredLines": 0,
"lineCoverage": 0,
"files": [
{
"coveredLines": 0,
"lineCoverage": 0,
"path": "Documents\/github\/ww\/ios-SuperApp\/Pods\/BundleA\/BundleA\/BundleA.m",
"functions": [
{
"coveredLines": 0,
"lineCoverage": 0,
"lineNumber": 3,
"executionCount": 0,
"name": "Some_function",
"executableLines": 10
}
],
"name": "SomeClass.m",
"executableLines": 10
}
],
"name": "BundleA.bundle",
"executableLines": 10,
"buildProductPath": "\/Library\/Developer\/Xcode\/DerivedData\/SuperApp-enbcwwvvobzujubcgbepwgrjngiy\/Build\/Products\/Debug-iphonesimulator\/BundleA\/BundleA.bundle\/BundleA"
},
{
"coveredLines": 27,
"lineCoverage": 0.2268907563,
"files": [
{
"coveredLines": 27,
"lineCoverage": 0.2268907563,
"path": "Documents\/github\/ww\/ios-SuperApp\/Pods\/SuperClass\/SuperClass\/SuperClass.m",
"functions": [
{
"coveredLines": 0,
"lineCoverage": 0,
"lineNumber": 85,
"executionCount": 0,
"name": "FLoat_ceil",
"executableLines": 45
},
{
"coveredLines": 24,
"lineCoverage": 1,
"lineNumber": 259,
"executionCount": 1,
"name": "+[SuperClass load]",
"executableLines": 24
},
{
"coveredLines": 3,
"lineCoverage": 0.14285714285714285,
"lineNumber": 311,
"executionCount": 1,
"name": "__26+[SuperClass load]_block",
"executableLines": 50
}
],
"name": "SuperClass.m",
"executableLines": 119
}
],
"name": "SuperClass.framework",
"executableLines": 119,
"buildProductPath": "\/Library\/Developer\/Xcode\/DerivedData\/SuperApp-enbcwwvvobzujubcgbepwgrjngiy\/Build\/Products\/Debug-iphonesimulator\/SuperClass\/SuperClass.framework\/SuperClass"
}
],
"executableLines": 129
}
@@ -0,0 +1,42 @@
package xccov

import (
"testing"

"gopkg.in/src-d/go-git.v4/plumbing/object"

"github.com/codeclimate/test-reporter/env"
"github.com/stretchr/testify/require"
)

func Test_Format(t *testing.T) {
gb := env.GitBlob
defer func() { env.GitBlob = gb }()
env.GitBlob = func(s string, c *object.Commit) (string, error) {
return s, nil
}

r := require.New(t)

rb := Formatter{
Path: "./xccov_example.json",
}
rep, err := rb.Format()
r.NoError(err)

r.InDelta(rep.CoveredPercent, 20.93, 1)

sf := rep.SourceFiles["Documents/github/ww/ios-SuperApp/Pods/BundleA/BundleA/BundleA.m"]
r.Equal(sf.CoveredPercent, 0.0)
sfLc := sf.LineCounts
r.Equal(sfLc.Covered, 0)
r.Equal(sfLc.Missed, 10)
r.Equal(sfLc.Total, 10)

sf = rep.SourceFiles["Documents/github/ww/ios-SuperApp/Pods/SuperClass/SuperClass/SuperClass.m"]
r.InDelta(sf.CoveredPercent, 22.68, 1)
sfLc = sf.LineCounts
r.Equal(sfLc.Covered, 27)
r.Equal(sfLc.Missed, 92)
r.Equal(sfLc.Total, 119)
}

0 comments on commit 3ee4f71

Please sign in to comment.
You can’t perform that action at this time.