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

GitHub actions format #315

Merged
merged 10 commits into from
Aug 26, 2023
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
17 changes: 17 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: ci

on:
pull_request:
push:

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: '1.20'
cache: true
- run: go build .
- run: ./gotestsum -f testname
1 change: 0 additions & 1 deletion .project/golangci-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ linters:
- deadcode
- depguard
- errcheck
- gocognit
- goconst
- gofmt
- goimports
Expand Down
2 changes: 2 additions & 0 deletions cmd/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ func (bufferCloser) Close() error { return nil }
func (bufferCloser) Sync() error { return nil }

func TestEventHandler_Event_WithMissingActionFail(t *testing.T) {
t.Setenv("GITHUB_ACTIONS", "no")

buf := new(bufferCloser)
errBuf := new(bytes.Buffer)
format := testjson.NewEventFormatter(errBuf, "testname", testjson.FormatOptions{})
Expand Down
4 changes: 3 additions & 1 deletion cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,9 @@ func setupFlags(name string) (*pflag.FlagSet, *options) {
flags.Usage = func() {
usage(os.Stdout, name, flags)
}

flags.StringVarP(&opts.format, "format", "f",
lookEnvWithDefault("GOTESTSUM_FORMAT", "short"),
lookEnvWithDefault("GOTESTSUM_FORMAT", "pkgname"),
"print format of test input")
flags.BoolVar(&opts.formatOptions.HideEmptyPackages, "format-hide-empty-pkg",
false, "do not print empty packages in compact formats")
Expand Down Expand Up @@ -139,6 +140,7 @@ Formats:
pkgname print a line for each package
pkgname-and-test-fails print a line for each package and failed test output
testname print a line for each test and package
github-actions testname format with github actions log grouping
standard-quiet standard go test format
standard-verbose standard go test -v format

Expand Down
3 changes: 3 additions & 0 deletions cmd/main_e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ func TestE2E_RerunFails(t *testing.T) {
if testing.Short() {
t.Skip("too slow for short run")
}
t.Setenv("GITHUB_ACTIONS", "no")

type testCase struct {
name string
Expand Down Expand Up @@ -220,6 +221,7 @@ func TestE2E_MaxFails_EndTestRun(t *testing.T) {
envVars["TEST_SEEDFILE"] = tmpFile.Path()
env.PatchAll(t, envVars)

t.Setenv("GOTESTSUM_FORMAT", "pkgname")
flags, opts := setupFlags("gotestsum")
args := []string{"--max-fails=2", "--packages=./testdata/e2e/flaky/", "--", "-tags=testdata"}
assert.NilError(t, flags.Parse(args))
Expand All @@ -244,6 +246,7 @@ func TestE2E_IgnoresWarnings(t *testing.T) {
if testing.Short() {
t.Skip("too slow for short run")
}
t.Setenv("GITHUB_ACTIONS", "no")

flags, opts := setupFlags("gotestsum")
args := []string{
Expand Down
3 changes: 2 additions & 1 deletion cmd/testdata/gotestsum-help-text
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ See https://pkg.go.dev/gotest.tools/gotestsum#section-readme for detailed docume

Flags:
--debug enabled debug logging
-f, --format string print format of test input (default "short")
-f, --format string print format of test input (default "pkgname")
--format-hide-empty-pkg do not print empty packages in compact formats
--format-hivis use high visibility characters in some formats
--hide-summary summary hide sections of the summary: skipped,failed,errors,output (default none)
Expand Down Expand Up @@ -36,6 +36,7 @@ Formats:
pkgname print a line for each package
pkgname-and-test-fails print a line for each package and failed test output
testname print a line for each test and package
github-actions testname format with github actions log grouping
standard-quiet standard go test format
standard-verbose standard go test -v format

Expand Down
6 changes: 0 additions & 6 deletions testjson/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,6 @@ func (e TestEvent) PackageEvent() bool {
return e.Test == ""
}

// ElapsedFormatted returns Elapsed formatted in the go test format, ex (0.00s).
func (e TestEvent) ElapsedFormatted() string {
return fmt.Sprintf("(%.2fs)", e.Elapsed)
}

// Bytes returns the serialized JSON bytes that were parsed to create the event.
func (e TestEvent) Bytes() []byte {
return e.raw
Expand Down Expand Up @@ -199,7 +194,6 @@ func (p *Package) addOutput(id int, output string) {
if strings.HasPrefix(output, "panic: ") {
p.panicked = true
}
// TODO: limit size of buffered test output
p.output[id] = append(p.output[id], output)
}

Expand Down
87 changes: 79 additions & 8 deletions testjson/format.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bufio"
"fmt"
"io"
"os"
"strings"

"github.com/fatih/color"
Expand Down Expand Up @@ -73,18 +74,22 @@ func standardJSONFormat(out io.Writer) EventFormatter {
})
}

func testNameFormatTestEvent(out io.Writer, event TestEvent) {
pkgPath := RelativePackagePath(event.Package)

fmt.Fprintf(out, "%s %s%s %s\n",
colorEvent(event)(strings.ToUpper(string(event.Action))),
joinPkgToTestName(pkgPath, event.Test),
formatRunID(event.RunID),
fmt.Sprintf("(%.2fs)", event.Elapsed))
}

func testNameFormat(out io.Writer) EventFormatter {
buf := bufio.NewWriter(out)
// nolint:errcheck
return eventFormatterFunc(func(event TestEvent, exec *Execution) error {
formatTest := func() error {
pkgPath := RelativePackagePath(event.Package)

fmt.Fprintf(buf, "%s %s%s %s\n",
colorEvent(event)(strings.ToUpper(string(event.Action))),
joinPkgToTestName(pkgPath, event.Test),
formatRunID(event.RunID),
event.ElapsedFormatted())
testNameFormatTestEvent(buf, event)
return buf.Flush()
}

Expand All @@ -101,6 +106,7 @@ func testNameFormat(out io.Writer) EventFormatter {
result := colorEvent(event)(strings.ToUpper(string(event.Action)))
pkg := exec.Package(event.Package)
if event.Action == ActionSkip || (event.Action == ActionPass && pkg.Total == 0) {
event.Action = ActionSkip // always color these as skip actions
result = colorEvent(event)("EMPTY")
}

Expand All @@ -116,7 +122,7 @@ func testNameFormat(out io.Writer) EventFormatter {
pkg.WriteOutputTo(buf, tc.ID)
return formatTest()

case event.Action == ActionPass:
case event.Action == ActionPass || event.Action == ActionSkip:
return formatTest()
}
return nil
Expand Down Expand Up @@ -307,12 +313,77 @@ func NewEventFormatter(out io.Writer, format string, formatOpts FormatOptions) E
case "dots-v2":
return newDotFormatter(out, formatOpts)
case "testname", "short-verbose":
if os.Getenv("GITHUB_ACTIONS") == "true" {
return githubActionsFormat(out)
}
return testNameFormat(out)
case "pkgname", "short":
return pkgNameFormat(out, formatOpts)
case "pkgname-and-test-fails", "short-with-failures":
return pkgNameWithFailuresFormat(out, formatOpts)
case "github-actions", "github-action":
return githubActionsFormat(out)
default:
return nil
}
}

func githubActionsFormat(out io.Writer) EventFormatter {
buf := bufio.NewWriter(out)

type name struct {
Package string
Test string
}
output := map[name][]string{}

return eventFormatterFunc(func(event TestEvent, exec *Execution) error {
key := name{Package: event.Package, Test: event.Test}

// test case output
if event.Test != "" && event.Action == ActionOutput {
if !isFramingLine(event.Output, event.Test) {
output[key] = append(output[key], event.Output)
}
return nil
}

// test case end event
if event.Test != "" && event.Action.IsTerminal() {
if len(output[key]) > 0 {
buf.WriteString("::group::")
} else {
buf.WriteString(" ")
}
testNameFormatTestEvent(buf, event)

for _, item := range output[key] {
buf.WriteString(item)
}
if len(output[key]) > 0 {
buf.WriteString("\n::endgroup::\n")
}
delete(output, key)
return buf.Flush()
}

// package event
if !event.Action.IsTerminal() {
return nil
}

result := colorEvent(event)(strings.ToUpper(string(event.Action)))
pkg := exec.Package(event.Package)
if event.Action == ActionSkip || (event.Action == ActionPass && pkg.Total == 0) {
event.Action = ActionSkip // always color these as skip actions
result = colorEvent(event)("EMPTY")
}

buf.WriteString(" ")
buf.WriteString(result)
buf.WriteString(" Package ")
buf.WriteString(packageLine(event, exec.Package(event.Package)))
buf.WriteString("\n")
return buf.Flush()
})
}
5 changes: 5 additions & 0 deletions testjson/format_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@ func TestFormats_DefaultGoTestJson(t *testing.T) {
format: standardJSONFormat,
expectedOut: "input/go-test-json.out",
},
{
name: "github-actions",
format: githubActionsFormat,
expectedOut: "format/github-actions.out",
},
}

for _, tc := range testCases {
Expand Down
16 changes: 6 additions & 10 deletions testjson/summary.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ func writeTestCaseSummary(out io.Writer, execution executionSummary, conf testCa
formatRunID(tc.RunID),
FormatDurationAsSeconds(tc.Elapsed, 2))
for _, line := range execution.OutputLines(tc) {
if isFramingLine(line) || conf.filter(tc.Test.Name(), line) {
if isFramingLine(line, tc.Test.Name()) {
continue
}
fmt.Fprint(out, line)
Expand All @@ -192,7 +192,6 @@ func writeTestCaseSummary(out io.Writer, execution executionSummary, conf testCa
type testCaseFormatConfig struct {
header string
prefix string
filter func(testName string, line string) bool
getter func(executionSummary) []TestCase
}

Expand All @@ -201,9 +200,6 @@ func formatFailed() testCaseFormatConfig {
return testCaseFormatConfig{
header: withColor("Failed"),
prefix: withColor("FAIL"),
filter: func(testName string, line string) bool {
return strings.HasPrefix(line, "--- FAIL: "+testName+" ")
},
getter: func(execution executionSummary) []TestCase {
return execution.Failed()
},
Expand All @@ -215,17 +211,17 @@ func formatSkipped() testCaseFormatConfig {
return testCaseFormatConfig{
header: withColor("Skipped"),
prefix: withColor("SKIP"),
filter: func(testName string, line string) bool {
return strings.HasPrefix(line, "--- SKIP: "+testName+" ")
},
getter: func(execution executionSummary) []TestCase {
return execution.Skipped()
},
}
}

func isFramingLine(line string) bool {
func isFramingLine(line string, testName string) bool {
return strings.HasPrefix(line, "=== RUN Test") ||
strings.HasPrefix(line, "=== PAUSE Test") ||
strings.HasPrefix(line, "=== CONT Test")
strings.HasPrefix(line, "=== CONT Test") ||
strings.HasPrefix(line, "--- FAIL: "+testName+" ") ||
strings.HasPrefix(line, "--- SKIP: "+testName+" ") ||
strings.HasPrefix(line, "--- PASS: "+testName+" ")
}
Loading