gotest.tools/gotestsum@v1.11.0/testjson/summary_test.go (about)

     1  package testjson
     2  
     3  import (
     4  	"bytes"
     5  	"io"
     6  	"strings"
     7  	"testing"
     8  	"time"
     9  
    10  	"gotest.tools/v3/assert"
    11  	"gotest.tools/v3/golden"
    12  )
    13  
    14  func TestSummary_String(t *testing.T) {
    15  	var testcases = []struct {
    16  		name     string
    17  		summary  Summary
    18  		expected string
    19  	}{
    20  		{
    21  			name:     "none",
    22  			summary:  SummarizeNone,
    23  			expected: "none",
    24  		},
    25  		{
    26  			name:     "all",
    27  			summary:  SummarizeAll,
    28  			expected: "skipped,failed,errors,output",
    29  		},
    30  		{
    31  			name:     "one value",
    32  			summary:  SummarizeErrors,
    33  			expected: "errors",
    34  		},
    35  		{
    36  			name:     "a few values",
    37  			summary:  SummarizeOutput | SummarizeSkipped | SummarizeErrors,
    38  			expected: "skipped,errors,output",
    39  		},
    40  	}
    41  	for _, tc := range testcases {
    42  		t.Run(tc.name, func(t *testing.T) {
    43  			assert.Equal(t, tc.summary.String(), tc.expected)
    44  		})
    45  	}
    46  }
    47  
    48  func TestPrintSummary_NoFailures(t *testing.T) {
    49  	patchTimeNow(t)
    50  
    51  	out := new(bytes.Buffer)
    52  	start := time.Now()
    53  	exec := &Execution{
    54  		started: start,
    55  		done:    true,
    56  		packages: map[string]*Package{
    57  			"foo":   {Total: 12},
    58  			"other": {Total: 1},
    59  		},
    60  	}
    61  	timeNow = func() time.Time {
    62  		return start.Add(34123111 * time.Microsecond)
    63  	}
    64  	PrintSummary(out, exec, SummarizeAll)
    65  
    66  	expected := "\nDONE 13 tests in 34.123s\n"
    67  	assert.Equal(t, out.String(), expected)
    68  }
    69  
    70  func TestPrintSummary_WithFailures(t *testing.T) {
    71  	patchPkgPathPrefix(t, "example.com")
    72  	patchTimeNow(t)
    73  
    74  	start := time.Now()
    75  	exec := &Execution{
    76  		started: start,
    77  		done:    true,
    78  		packages: map[string]*Package{
    79  			"example.com/project/fs": {
    80  				Total: 12,
    81  				Failed: []TestCase{
    82  					{
    83  						Package: "example.com/project/fs",
    84  						Test:    "TestFileDo",
    85  						Elapsed: 1411 * time.Millisecond,
    86  						ID:      1,
    87  					},
    88  					{
    89  						Package: "example.com/project/fs",
    90  						Test:    "TestFileDoError",
    91  						Elapsed: 12 * time.Millisecond,
    92  						ID:      2,
    93  					},
    94  				},
    95  				output: map[int][]string{
    96  					1: multiLine(`=== RUN   TestFileDo
    97  Some stdout/stderr here
    98  --- FAIL: TestFileDo (1.41s)
    99  	do_test.go:33 assertion failed
   100  `),
   101  					2: multiLine(`=== RUN   TestFileDoError
   102  --- FAIL: TestFileDoError (0.01s)
   103  	do_test.go:50 assertion failed: expected nil error, got WHAT!
   104  `),
   105  					0: multiLine("FAIL\n"),
   106  				},
   107  				action: ActionFail,
   108  			},
   109  			"example.com/project/pkg/more": {
   110  				Total: 1,
   111  				Failed: []TestCase{
   112  					{
   113  						Package: "example.com/project/pkg/more",
   114  						Test:    "TestAlbatross",
   115  						Elapsed: 40 * time.Millisecond,
   116  						ID:      1,
   117  					},
   118  				},
   119  				Skipped: []TestCase{
   120  					{
   121  						Package: "example.com/project/pkg/more",
   122  						Test:    "TestOnlySometimes",
   123  						Elapsed: 0,
   124  						ID:      2,
   125  					},
   126  				},
   127  				output: map[int][]string{
   128  					1: multiLine(`=== RUN   TestAlbatross
   129  --- FAIL: TestAlbatross (0.04s)
   130  `),
   131  					2: multiLine(`=== RUN   TestOnlySometimes
   132  --- SKIP: TestOnlySometimes (0.00s)
   133  	good_test.go:27: the skip message
   134  `),
   135  				},
   136  			},
   137  			"example.com/project/badmain": {
   138  				action: ActionFail,
   139  				output: map[int][]string{
   140  					0: multiLine("sometimes main can exit 2\n"),
   141  				},
   142  			},
   143  		},
   144  		errors: []string{
   145  			"pkg/file.go:99:12: missing ',' before newline",
   146  		},
   147  	}
   148  	timeNow = func() time.Time {
   149  		return start.Add(34123111 * time.Microsecond)
   150  	}
   151  
   152  	t.Run("summarize all", func(t *testing.T) {
   153  		out := new(bytes.Buffer)
   154  		PrintSummary(out, exec, SummarizeAll)
   155  
   156  		expected := `
   157  === Skipped
   158  === SKIP: project/pkg/more TestOnlySometimes (0.00s)
   159  	good_test.go:27: the skip message
   160  
   161  === Failed
   162  === FAIL: project/badmain  (0.00s)
   163  sometimes main can exit 2
   164  
   165  === FAIL: project/fs TestFileDo (1.41s)
   166  Some stdout/stderr here
   167  	do_test.go:33 assertion failed
   168  
   169  === FAIL: project/fs TestFileDoError (0.01s)
   170  	do_test.go:50 assertion failed: expected nil error, got WHAT!
   171  
   172  === FAIL: project/pkg/more TestAlbatross (0.04s)
   173  
   174  === Errors
   175  pkg/file.go:99:12: missing ',' before newline
   176  
   177  DONE 13 tests, 1 skipped, 4 failures, 1 error in 34.123s
   178  `
   179  		assert.Equal(t, out.String(), expected)
   180  	})
   181  
   182  	t.Run("summarize no output", func(t *testing.T) {
   183  		out := new(bytes.Buffer)
   184  		PrintSummary(out, exec, SummarizeAll-SummarizeOutput)
   185  
   186  		expected := `
   187  === Skipped
   188  === SKIP: project/pkg/more TestOnlySometimes (0.00s)
   189  
   190  === Failed
   191  === FAIL: project/badmain  (0.00s)
   192  === FAIL: project/fs TestFileDo (1.41s)
   193  === FAIL: project/fs TestFileDoError (0.01s)
   194  === FAIL: project/pkg/more TestAlbatross (0.04s)
   195  
   196  === Errors
   197  pkg/file.go:99:12: missing ',' before newline
   198  
   199  DONE 13 tests, 1 skipped, 4 failures, 1 error in 34.123s
   200  `
   201  		assert.Equal(t, out.String(), expected)
   202  	})
   203  
   204  	t.Run("summarize only errors", func(t *testing.T) {
   205  		out := new(bytes.Buffer)
   206  		PrintSummary(out, exec, SummarizeErrors)
   207  
   208  		expected := `
   209  === Errors
   210  pkg/file.go:99:12: missing ',' before newline
   211  
   212  DONE 13 tests, 1 skipped, 4 failures, 1 error in 34.123s
   213  `
   214  		assert.Equal(t, out.String(), expected)
   215  	})
   216  }
   217  
   218  func patchTimeNow(t *testing.T) {
   219  	timeNow = func() time.Time {
   220  		return time.Date(2022, 1, 2, 3, 4, 5, 600, time.UTC)
   221  	}
   222  	t.Cleanup(func() {
   223  		timeNow = time.Now
   224  	})
   225  }
   226  
   227  func multiLine(s string) []string {
   228  	return strings.SplitAfter(s, "\n")
   229  }
   230  
   231  func TestPrintSummary(t *testing.T) {
   232  	patchTimeNow(t)
   233  
   234  	type testCase struct {
   235  		name        string
   236  		config      func(t *testing.T) ScanConfig
   237  		expectedOut string
   238  		expected    func(t *testing.T, exec *Execution)
   239  	}
   240  
   241  	run := func(t *testing.T, tc testCase) {
   242  		exec, err := ScanTestOutput(tc.config(t))
   243  		assert.NilError(t, err)
   244  
   245  		buf := new(bytes.Buffer)
   246  		PrintSummary(buf, exec, SummarizeAll)
   247  		golden.Assert(t, buf.String(), tc.expectedOut)
   248  
   249  		if tc.expected != nil {
   250  			tc.expected(t, exec)
   251  		}
   252  	}
   253  
   254  	testCases := []testCase{
   255  		{
   256  			name:        "missing test fail event",
   257  			config:      scanConfigFromGolden("input/go-test-json-missing-test-fail.out"),
   258  			expectedOut: "summary/missing-test-fail-event",
   259  			expected: func(t *testing.T, exec *Execution) {
   260  				for name, pkg := range exec.packages {
   261  					assert.Equal(t, len(pkg.running), 0, "package %v still had tests in running", name)
   262  				}
   263  			},
   264  		},
   265  		{
   266  			name:        "output attributed to wrong test",
   267  			config:      scanConfigFromGolden("input/go-test-json-misattributed.out"),
   268  			expectedOut: "summary/misattributed-output",
   269  		},
   270  		{
   271  			name:        "with subtest failures",
   272  			config:      scanConfigFromGolden("input/go-test-json.out"),
   273  			expectedOut: "summary/root-test-has-subtest-failures",
   274  		},
   275  		{
   276  			name:        "with parallel failures",
   277  			config:      scanConfigFromGolden("input/go-test-json-with-parallel-fails.out"),
   278  			expectedOut: "summary/parallel-failures",
   279  		},
   280  		{
   281  			name:        "missing skip message",
   282  			config:      scanConfigFromGolden("input/go-test-json-missing-skip-msg.out"),
   283  			expectedOut: "summary/bug-missing-skip-message",
   284  		},
   285  		{
   286  			name: "repeated test case",
   287  			config: func(t *testing.T) ScanConfig {
   288  				in := golden.Get(t, "input/go-test-json.out")
   289  				return ScanConfig{
   290  					Stdout: io.MultiReader(
   291  						bytes.NewReader(in),
   292  						bytes.NewReader(in),
   293  						bytes.NewReader(in)),
   294  				}
   295  			},
   296  			expectedOut: "summary/bug-repeated-test-case-output",
   297  		},
   298  		{
   299  			name: "with rerun id",
   300  			config: func(t *testing.T) ScanConfig {
   301  				return ScanConfig{
   302  					Stdout: bytes.NewReader(golden.Get(t, "input/go-test-json.out")),
   303  					RunID:  7,
   304  				}
   305  			},
   306  			expectedOut: "summary/with-run-id",
   307  		},
   308  	}
   309  
   310  	for _, tc := range testCases {
   311  		t.Run(tc.name, func(t *testing.T) {
   312  			run(t, tc)
   313  		})
   314  	}
   315  }
   316  
   317  func scanConfigFromGolden(filename string) func(t *testing.T) ScanConfig {
   318  	return func(t *testing.T) ScanConfig {
   319  		return ScanConfig{Stdout: bytes.NewReader(golden.Get(t, filename))}
   320  	}
   321  }