Skip to content

Commit

Permalink
Merge branch 'gotestyourself:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
nickajacks1 authored Feb 5, 2024
2 parents 5f4ccd4 + bc98120 commit f88d13c
Show file tree
Hide file tree
Showing 50 changed files with 2,325 additions and 1,213 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
9 changes: 9 additions & 0 deletions .project/goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ builds:
- freebsd
- windows
- linux
- illumos
goarch:
- amd64
- arm64
Expand All @@ -36,6 +37,14 @@ builds:
goarch: s390x
- goos: windows
goarch: ppc64le
- goos: illumos
goarch: arm
- goos: illumos
goarch: arm64
- goos: illumos
goarch: s390x
- goos: illumos
goarch: ppc64le

checksum:
name_template: '{{ .ProjectName }}-{{ .Version }}-checksums.txt'
18 changes: 14 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,16 @@ The `--format` flag or `GOTESTSUM_FORMAT` environment variable set the format th
is used to print the test names, and possibly test output, as the tests run. Most
outputs use color to highlight pass, fail, or skip.

The `--format-hivis` flag changes the icons used by `pkgname` formats to higher
visiblity unicode characters.
The `--format-icons` flag changes the icons used by `pkgname` and `testdox` formats.
You can set the `GOTESTSUM_FORMAT_ICONS` environment variable, instead of the flag.
The nerdfonts icons requires a font from [Nerd Fonts](https://www.nerdfonts.com/).

Commonly used formats (see `--help` for a full list):

* `dots` - print a character for each test.
* `pkgname` (default) - print a line for each package.
* `testname` - print a line for each test and package.
* `testdox` - print a sentence for each test using [gotestdox](https://github.com/bitfield/gotestdox).
* `standard-quiet` - the standard `go test` format.
* `standard-verbose` - the standard `go test -v` format.

Expand Down Expand Up @@ -139,7 +141,8 @@ test run has completed. The binary will be run with the following environment
variables set:

```
GOTESTSUM_FORMAT # gotestsum format (ex: short)
GOTESTSUM_ELAPSED # test run time in seconds (ex: 2.45s)
GOTESTSUM_FORMAT # gotestsum format (ex: pkgname)
GOTESTSUM_JSONFILE # path to the jsonfile, empty if no file path was given
GOTESTSUM_JUNITFILE # path to the junit.xml file, empty if no file path was given
TESTS_ERRORS # number of errors
Expand All @@ -158,9 +161,15 @@ package may be used to parse the JSON file output.

First install the example notification command with `go get gotest.tools/gotestsum/contrib/notify`.
The command will be downloaded to `$GOPATH/bin` as `notify`. Note that this
example `notify` command only works on macOS with
example `notify` command only works on Linux with `notify-send` and on macOS with
[terminal-notifer](https://github.com/julienXX/terminal-notifier) installed.

On Linux, you need to have some "test-pass" and "test-fail" icons installed in your icon theme.
Some sample icons can be found in `contrib/notify`, and can be installed with `make install`.

On Windows, you can install [notify-send.exe](https://github.com/vaskovsky/notify-send)
but it does not support custom icons so will have to use the basic "info" and "error".

```
gotestsum --post-run-command notify
```
Expand Down Expand Up @@ -438,6 +447,7 @@ The projects below use (or have used) gotestsum.
* [dex](https://github.com/dexidp/dex/blob/master/Makefile)
* [coder](https://github.com/coder/coder/blob/main/Makefile)
* [docker/cli](https://github.com/docker/cli/blob/master/Makefile)
* [mattermost](https://github.com/mattermost/mattermost/blob/master/server/Makefile)

Please open a GitHub issue or pull request to add or remove projects from this list.

Expand Down
10 changes: 10 additions & 0 deletions cmd/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,14 @@ func newEventHandler(opts *options) (*eventHandler, error) {
err: bufio.NewWriter(opts.stderr),
maxFails: opts.maxFails,
}

switch opts.format {
case "dots", "dots-v1", "dots-v2":
// Discard the error from the handler to prevent extra lines. The
// error will be printed in the summary.
handler.err = bufio.NewWriter(io.Discard)
}

var err error
if opts.jsonFile != "" {
_ = os.MkdirAll(filepath.Dir(opts.jsonFile), 0o755)
Expand Down Expand Up @@ -153,6 +161,7 @@ func postRunHook(opts *options, execution *testjson.Execution) error {
if len(command) == 0 {
return nil
}
log.Debugf("exec: %s", command)

cmd := exec.Command(command[0], command[1:]...)
cmd.Stdout = opts.stdout
Expand All @@ -162,6 +171,7 @@ func postRunHook(opts *options, execution *testjson.Execution) error {
"GOTESTSUM_JSONFILE="+opts.jsonFile,
"GOTESTSUM_JSONFILE_TIMING_EVENTS="+opts.jsonFileTimingEvents,
"GOTESTSUM_JUNITFILE="+opts.junitFile,
fmt.Sprintf("GOTESTSUM_ELAPSED=%.3fs", execution.Elapsed().Seconds()),
fmt.Sprintf("TESTS_TOTAL=%d", execution.Total()),
fmt.Sprintf("TESTS_FAILED=%d", len(execution.Failed())),
fmt.Sprintf("TESTS_SKIPPED=%d", len(execution.Skipped())),
Expand Down
58 changes: 55 additions & 3 deletions cmd/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@ package cmd

import (
"bytes"
"io/ioutil"
"io"
"os"
"path/filepath"
"strings"
"testing"

"gotest.tools/gotestsum/internal/junitxml"
"gotest.tools/gotestsum/internal/text"
"gotest.tools/gotestsum/testjson"
"gotest.tools/v3/assert"
"gotest.tools/v3/assert/cmp"
"gotest.tools/v3/env"
"gotest.tools/v3/fs"
"gotest.tools/v3/golden"
Expand All @@ -30,11 +33,21 @@ func TestPostRunHook(t *testing.T) {
}

env.Patch(t, "GOTESTSUM_FORMAT", "short")
env.Patch(t, "GOTESTSUM_FORMAT_ICONS", "default")

exec := newExecFromTestData(t)
err = postRunHook(opts, exec)
assert.NilError(t, err)
golden.Assert(t, buf.String(), "post-run-hook-expected")

actual := text.ProcessLines(t, buf, func(line string) string {
if strings.HasPrefix(line, "GOTESTSUM_ELAPSED=0.0") &&
strings.HasSuffix(line, "s") {
i := strings.Index(line, "=")
return line[:i] + "=0.000s"
}
return line
})
golden.Assert(t, actual, "post-run-hook-expected")
}

func newExecFromTestData(t *testing.T) *testjson.Execution {
Expand All @@ -60,6 +73,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 All @@ -79,7 +94,7 @@ func TestEventHandler_Event_WithMissingActionFail(t *testing.T) {
}

func TestEventHandler_Event_MaxFails(t *testing.T) {
format := testjson.NewEventFormatter(ioutil.Discard, "testname", testjson.FormatOptions{})
format := testjson.NewEventFormatter(io.Discard, "testname", testjson.FormatOptions{})

source := golden.Get(t, "../../testjson/testdata/input/go-test-json.out")
cfg := testjson.ScanConfig{
Expand Down Expand Up @@ -123,3 +138,40 @@ func TestWriteJunitFile_CreatesDirectory(t *testing.T) {
_, err = os.Stat(junitFile)
assert.NilError(t, err)
}

func TestScanTestOutput_TestTimeoutPanicRace(t *testing.T) {
run := func(t *testing.T, name string) {
format := testjson.NewEventFormatter(io.Discard, "testname", testjson.FormatOptions{})

source := golden.Get(t, "input/go-test-json-"+name+".out")
cfg := testjson.ScanConfig{
Stdout: bytes.NewReader(source),
Handler: &eventHandler{formatter: format},
}
exec, err := testjson.ScanTestOutput(cfg)
assert.NilError(t, err)

out := new(bytes.Buffer)
testjson.PrintSummary(out, exec, testjson.SummarizeAll)

actual := text.ProcessLines(t, out, text.OpRemoveSummaryLineElapsedTime)
golden.Assert(t, actual, "expected/"+name+"-summary")

var buf bytes.Buffer
err = junitxml.Write(&buf, exec, junitxml.Config{})
assert.NilError(t, err)

assert.Assert(t, cmp.Contains(buf.String(), "panic: test timed out"))
}

testCases := []string{
"panic-race-1",
"panic-race-2",
}

for _, tc := range testCases {
t.Run(tc, func(t *testing.T) {
run(t, tc)
})
}
}
30 changes: 24 additions & 6 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,18 @@ 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")
flags.BoolVar(&opts.formatOptions.UseHiVisibilityIcons, "format-hivis",
false, "use high visibility characters in some formats")
_ = flags.MarkHidden("format-hivis")
flags.StringVar(&opts.formatOptions.Icons, "format-icons",
lookEnvWithDefault("GOTESTSUM_FORMAT_ICONS", ""),
"use different icons, see help for options")
flags.BoolVar(&opts.rawCommand, "raw-command", false,
"don't prepend 'go test -json' to the 'go test' command")
flags.BoolVar(&opts.ignoreNonJSONOutputLines, "ignore-non-json-output-lines", false,
Expand All @@ -74,7 +79,7 @@ func setupFlags(name string) (*pflag.FlagSet, *options) {
flags.StringVar(&opts.jsonFileTimingEvents, "jsonfile-timing-events",
lookEnvWithDefault("GOTESTSUM_JSONFILE_TIMING_EVENTS", ""),
"write only the pass, skip, and fail TestEvents to the file")
flags.BoolVar(&opts.noColor, "no-color", defaultNoColor, "disable color output")
flags.BoolVar(&opts.noColor, "no-color", defaultNoColor(), "disable color output")

flags.Var(opts.hideSummary, "no-summary",
"do not print summary of: "+testjson.SummarizeAll.String())
Expand Down Expand Up @@ -139,9 +144,19 @@ 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
testdox print a sentence for each test using gotestdox
github-actions testname format with github actions log grouping
standard-quiet standard go test format
standard-verbose standard go test -v format
Format icons:
default the original unicode (✓, ∅, ✖)
hivis higher visibility unicode (✅, ➖, ❌)
text simple text characters (PASS, SKIP, FAIL)
codicons requires a font from https://www.nerdfonts.com/ (  )
octicons requires a font from https://www.nerdfonts.com/ (  )
emoticons requires a font from https://www.nerdfonts.com/ (󰇵 󰇶 󰇸)
Commands:
%[1]s tool slowest find or skip the slowest tests
%[1]s help print this help next
Expand Down Expand Up @@ -200,12 +215,12 @@ func (o options) Validate() error {
return nil
}

var defaultNoColor = func() bool {
func defaultNoColor() bool {
// fatih/color will only output color when stdout is a terminal which is not
// true for many CI environments which support color output. So instead, we
// try to detect these CI environments via their environment variables.
// This code is based on https://github.com/jwalton/go-supportscolor
if _, exists := os.LookupEnv("CI"); exists {
if value, exists := os.LookupEnv("CI"); exists {
var ciEnvNames = []string{
"APPVEYOR",
"BUILDKITE",
Expand All @@ -224,12 +239,15 @@ var defaultNoColor = func() bool {
if os.Getenv("CI_NAME") == "codeship" {
return false
}
if value == "woodpecker" {
return false
}
}
if _, exists := os.LookupEnv("TEAMCITY_VERSION"); exists {
return false
}
return color.NoColor
}()
}

func setupLogging(opts *options) {
if opts.debug {
Expand Down Expand Up @@ -317,7 +335,7 @@ func goTestCmdArgs(opts *options, rerunOpts rerunOpts) []string {
return result
}

args := opts.args
args := append([]string{}, opts.args...)
result := []string{"go", "test"}

if len(args) == 0 {
Expand Down
7 changes: 5 additions & 2 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 All @@ -43,7 +44,7 @@ func TestE2E_RerunFails(t *testing.T) {

envVars := osEnviron()
envVars["TEST_SEEDFILE"] = tmpFile.Path()
defer env.PatchAll(t, envVars)()
env.PatchAll(t, envVars)

flags, opts := setupFlags("gotestsum")
assert.NilError(t, flags.Parse(tc.args))
Expand Down Expand Up @@ -218,8 +219,9 @@ func TestE2E_MaxFails_EndTestRun(t *testing.T) {

envVars := osEnviron()
envVars["TEST_SEEDFILE"] = tmpFile.Path()
defer env.PatchAll(t, envVars)()
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
Loading

0 comments on commit f88d13c

Please sign in to comment.