Skip to content

Commit

Permalink
Merge pull request #315 from gotestyourself/github-actions-format
Browse files Browse the repository at this point in the history
GitHub actions format
  • Loading branch information
dnephin authored Aug 26, 2023
2 parents e7c9840 + 2913209 commit 73827dd
Show file tree
Hide file tree
Showing 14 changed files with 344 additions and 27 deletions.
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

0 comments on commit 73827dd

Please sign in to comment.