Skip to content
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
7 changes: 2 additions & 5 deletions pkg/testcoverage/check_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,9 +278,7 @@ func TestCheck(t *testing.T) {
pass, err := Check(buf, cfg)
assert.False(t, pass)
assert.NoError(t, err)

// Should report missing explanations
assert.Contains(t, buf.String(), "Files with missing explanations for coverage-ignore")
assert.Contains(t, buf.String(), "Files with missing explanation for coverage-ignore")
})

t.Run("valid profile - pass when not checking for explanations", func(t *testing.T) {
Expand All @@ -295,8 +293,6 @@ func TestCheck(t *testing.T) {
pass, err := Check(buf, cfg)
assert.True(t, pass)
assert.NoError(t, err)

// Should not report missing explanations
assert.NotContains(t, buf.String(), "Files with missing explanations for coverage-ignore")
})
}
Expand Down Expand Up @@ -674,6 +670,7 @@ func Test_Analyze(t *testing.T) {
}
result = Analyze(cfg, stats, nil)
assert.False(t, result.Pass())
assert.True(t, result.PassCoverage())
assert.NotEmpty(t, result.FilesWithMissingExplanations)
})
}
Expand Down
31 changes: 15 additions & 16 deletions pkg/testcoverage/coverage/cover.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,7 @@ func coverageForFile(profile *cover.Profile, fi fileInfo, forceComment bool) (St

s := sumCoverage(profile, funcs, blocks, annotations)
s.Name = fi.name

s.AnnotationsWithoutComments = make([]int, len(withoutComment))
for i, extent := range withoutComment {
s.AnnotationsWithoutComments[i] = extent.StartLine
}
s.AnnotationsWithoutComments = pluckStartLine(withoutComment)

return s, nil
}
Expand Down Expand Up @@ -266,23 +262,17 @@ func findAnnotations(source []byte, forceComment bool) ([]extent, []extent, erro
return nil, nil, fmt.Errorf("can't parse comments: %w", err)
}

var validAnnotations []extent

var annotationsWithoutComment []extent
var validAnnotations, annotationsWithoutComment []extent //nolint:prealloc // relax

for _, c := range node.Comments {
if !strings.Contains(c.Text(), IgnoreText) {
continue // does not have annotation continue to next comment
}

if forceComment {
if hasComment(c.Text()) {
validAnnotations = append(validAnnotations, newExtent(fset, c))
} else {
annotationsWithoutComment = append(annotationsWithoutComment, newExtent(fset, c))
}
} else {
validAnnotations = append(validAnnotations, newExtent(fset, c))
validAnnotations = append(validAnnotations, newExtent(fset, c))

if forceComment && !hasComment(c.Text()) {
annotationsWithoutComment = append(annotationsWithoutComment, newExtent(fset, c))
}
}

Expand Down Expand Up @@ -377,6 +367,15 @@ func hasExtentWithStartLine(ee []extent, startLine int) bool {
return found
}

func pluckStartLine(extents []extent) []int {
res := make([]int, len(extents))
for i, e := range extents {
res[i] = e.StartLine
}

return res
}

func sumCoverage(profile *cover.Profile, funcs, blocks, annotations []extent) Stats {
s := Stats{}

Expand Down
19 changes: 5 additions & 14 deletions pkg/testcoverage/coverage/cover_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ func Test_findAnnotations(t *testing.T) {

comments, _, err := FindAnnotations([]byte(source), false)
assert.NoError(t, err)
assert.Equal(t, []int{3, 5}, pluckStartLine(comments))
assert.Equal(t, []int{3, 5}, PluckStartLine(comments))
}

func Test_findAnnotationsWithComment(t *testing.T) {
Expand Down Expand Up @@ -169,12 +169,12 @@ func Test_findAnnotationsWithComment(t *testing.T) {

validAnnotations, withoutComment, err := FindAnnotations([]byte(source), true)
assert.NoError(t, err)
assert.Equal(t, []int{6}, pluckStartLine(validAnnotations))
assert.Equal(t, []int{3, 9}, pluckStartLine(withoutComment))
assert.Equal(t, []int{3, 6, 9}, PluckStartLine(validAnnotations))
assert.Equal(t, []int{3, 9}, PluckStartLine(withoutComment))

validAnnotations, withoutComment, err = FindAnnotations([]byte(source), false)
assert.NoError(t, err)
assert.Equal(t, []int{3, 6, 9}, pluckStartLine(validAnnotations))
assert.Equal(t, []int{3, 6, 9}, PluckStartLine(validAnnotations))
assert.Empty(t, withoutComment)
}

Expand Down Expand Up @@ -218,7 +218,7 @@ func Test_findFuncs(t *testing.T) {

funcs, blocks, err := FindFuncsAndBlocks([]byte(source))
assert.NoError(t, err)
assert.Equal(t, []int{3, 6, 13, 20}, pluckStartLine(funcs))
assert.Equal(t, []int{3, 6, 13, 20}, PluckStartLine(funcs))
assert.Equal(t, []Extent{
{8, 16, 10, 4},
{15, 22, 17, 4},
Expand Down Expand Up @@ -262,12 +262,3 @@ func Test_sumCoverage(t *testing.T) {
}}
assert.Equal(t, expected, s)
}

func pluckStartLine(extents []Extent) []int {
res := make([]int, len(extents))
for i, e := range extents {
res[i] = e.StartLine
}

return res
}
1 change: 1 addition & 0 deletions pkg/testcoverage/coverage/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ var (
ParseProfiles = parseProfiles
SumCoverage = sumCoverage
FindGoModFile = findGoModFile
PluckStartLine = pluckStartLine
)

type Extent = extent
46 changes: 23 additions & 23 deletions pkg/testcoverage/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"io"
"os"
"strconv"
"strings"
"text/tabwriter"

"github.com/vladopajic/go-test-coverage/v2/pkg/testcoverage/badge"
Expand Down Expand Up @@ -68,7 +69,7 @@ func reportIssuesForHuman(w io.Writer, coverageStats []coverage.Stats) {
}

func reportUncoveredLines(w io.Writer, result AnalyzeResult) {
if result.Pass() || len(result.FilesWithUncoveredLines) == 0 {
if result.PassCoverage() || len(result.FilesWithUncoveredLines) == 0 {
return
}

Expand Down Expand Up @@ -96,21 +97,16 @@ func reportMissingExplanations(w io.Writer, result AnalyzeResult) {
tabber := tabwriter.NewWriter(w, 1, 8, 2, '\t', 0) //nolint:mnd // relax
defer tabber.Flush()

fmt.Fprintf(tabber, "\nFiles with missing explanations for coverage-ignore annotations:")
fmt.Fprintf(tabber, "\nFiles with missing explanation for coverage-ignore annotation:")
fmt.Fprintf(tabber, "\n file:\tline numbers:")

for _, stats := range result.FilesWithMissingExplanations {
if len(stats.AnnotationsWithoutComments) == 0 {
if len(stats.AnnotationsWithoutComments) == 0 { // coverage-ignore
continue
}

fmt.Fprintf(tabber, "\n %s\t", stats.Name)

separator := ""
for _, ann := range stats.AnnotationsWithoutComments {
fmt.Fprintf(tabber, "%s%d", separator, ann)
separator = ", "
}
lines := sliceIntsStr(stats.AnnotationsWithoutComments, ", ")
fmt.Fprintf(tabber, "\n %s\t%s", stats.Name, lines)
}

fmt.Fprintf(tabber, "\n")
Expand Down Expand Up @@ -159,8 +155,8 @@ func ReportForGithubAction(w io.Writer, result AnalyzeResult) {
out := bufio.NewWriter(w)
defer out.Flush()

reportLineError := func(file, title, msg string) {
fmt.Fprintf(out, "::error file=%s,title=%s,line=1::%s\n", file, title, msg)
reportLineError := func(file, title, msg string, line int) {
fmt.Fprintf(out, "::error file=%s,title=%s,line=%d::%s\n", file, title, line, msg)
}
reportError := func(title, msg string) {
fmt.Fprintf(out, "::error title=%s::%s\n", title, msg)
Expand All @@ -172,7 +168,7 @@ func ReportForGithubAction(w io.Writer, result AnalyzeResult) {
"%s: coverage: %s; threshold: %d%%",
title, stats.Str(), stats.Threshold,
)
reportLineError(stats.Name, title, msg)
reportLineError(stats.Name, title, msg, 1)
}

for _, stats := range result.PackagesBelowThreshold {
Expand All @@ -193,17 +189,12 @@ func ReportForGithubAction(w io.Writer, result AnalyzeResult) {
reportError(title, msg)
}

// Report missing explanations for coverage-ignore annotations
for _, stats := range result.FilesWithMissingExplanations {
if len(stats.AnnotationsWithoutComments) > 0 {
for _, ann := range stats.AnnotationsWithoutComments {
title := "Missing explanation for coverage-ignore"
msg := title + ": add an explanation after the coverage-ignore annotation"

file := stats.Name
lineNumber := ann
fmt.Fprintf(out, "::error file=%s,title=%s,line=%d::%s\n", file, title, lineNumber, msg)
}
for _, line := range stats.AnnotationsWithoutComments {
title := "Missing explanation for coverage-ignore"
msg := title + ": add an explanation after the coverage-ignore annotation"

reportLineError(stats.Name, title, msg, line)
}
}
}
Expand Down Expand Up @@ -292,3 +283,12 @@ func statusStr(passing bool) string {

return "FAIL"
}

func sliceIntsStr(s []int, sep string) string {
strs := make([]string, len(s))
for i, v := range s {
strs[i] = strconv.Itoa(v)
}

return strings.Join(strs, sep)
}
22 changes: 1 addition & 21 deletions pkg/testcoverage/report_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -344,31 +344,11 @@ func Test_ReportMissingExplanations(t *testing.T) {
ReportForHuman(buf, result)

output := buf.String()
assert.Contains(t, output, "Files with missing explanations for coverage-ignore annotations:")
assert.Contains(t, output, "Files with missing explanation for coverage-ignore annotation:")
assert.Contains(t, output, "test.go")
assert.Contains(t, output, "10, 20")
})

t.Run("with empty annotations list", func(t *testing.T) {
t.Parallel()

buf := &bytes.Buffer{}
result := AnalyzeResult{
FilesWithMissingExplanations: []coverage.Stats{
{
Name: "test.go",
AnnotationsWithoutComments: []int{},
},
},
}

ReportForHuman(buf, result)

output := buf.String()
// Should not contain the file with empty annotations
assert.NotContains(t, output, "test.go\t")
})

t.Run("with no missing explanations", func(t *testing.T) {
t.Parallel()

Expand Down
7 changes: 7 additions & 0 deletions pkg/testcoverage/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ func (r *AnalyzeResult) Pass() bool {
len(r.FilesWithMissingExplanations) == 0
}

func (r *AnalyzeResult) PassCoverage() bool {
return r.MeetsTotalCoverage() &&
len(r.FilesBelowThreshold) == 0 &&
len(r.PackagesBelowThreshold) == 0 &&
r.MeetsDiffThreshold()
}

func (r *AnalyzeResult) MeetsDiffThreshold() bool {
if r.DiffThreshold == nil || !r.HasBaseBreakdown {
return true
Expand Down
Loading