Skip to content

Commit 3ac9ab4

Browse files
committed
fix some more interesting edge cases
1 parent 1cd4a6f commit 3ac9ab4

7 files changed

+91
-39
lines changed

.circleci/config.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ orbs:
55
jobs:
66
test:
77
docker:
8-
- image: cimg/go:1.18
8+
- image: cimg/go:1.17
99
steps:
1010
- checkout
1111
- run: go version

README.md

+12-7
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ will run the command:
7373

7474
`go test -json -run ParseJSON`
7575

76-
You can supply a list of packages to test, or any other arguments or flags understood by `go test`. However, `gotestdox` only prints events about *tests* (ignoring benchmarks and examples).
76+
You can supply a list of packages to test, or any other arguments or flags understood by `go test`. However, `gotestdox` only prints events about *tests* (ignoring benchmarks and examples). It doesn't report fuzz tests, since they don't tend to have useful names.
7777

7878
## Multiple packages
7979

@@ -271,32 +271,37 @@ Here is the complete `gotestdox` rendering of its own tests (sorted for readabil
271271
```
272272
github.com/bitfield/gotestdox:
273273
✔ EventString formats pass and fail events differently (0.00s)
274-
✔ ExecGoTest returns not OK when command errors (0.02s)
275-
✔ ExecGoTest returns not OK when tests fail (0.79s)
276-
✔ ExecGoTest returns OK when tests pass (0.66s)
277-
✔ Filter returns not OK on parsing error (0.00s)
274+
✔ ExecGoTest sets OK to false when command errors (0.03s)
275+
✔ ExecGoTest sets OK to false when tests fail (0.76s)
276+
✔ ExecGoTest sets OK to true when tests pass (0.90s)
278277
✔ Filter sets OK to false if any test fails (0.01s)
279-
✔ Filter sets OK to true if there are no test failures (0.01s)
278+
✔ Filter sets OK to false on parsing error (0.00s)
279+
✔ Filter sets OK to true if there are no test failures (0.00s)
280280
✔ NewTestDoxer returns testdoxer with standard IO streams (0.00s)
281281
✔ ParseJSON errors on invalid JSON (0.00s)
282282
✔ ParseJSON returns valid data for valid JSON (0.00s)
283283
Prettify (0.00s)
284284
✔ Prettify correctly renders a well-formed test name (0.00s)
285+
✔ Prettify does not break words when a digit follows an = sign (0.00s)
285286
✔ Prettify does not erase the final digit in words that end with a digit (0.00s)
286287
✔ Prettify does not treat an underscore in a subtest name as marking the end of a multiword function name (0.00s)
287288
✔ Prettify doesn't incorrectly title-case single-letter words (0.00s)
288289
✔ Prettify eliminates any words containing underscores after splitting (0.00s)
290+
✔ Prettify handles a test with no name, but with subtests (0.00s)
289291
✔ Prettify handles multiple underscores, with the first marking the end of a multiword function name (0.00s)
290292
✔ Prettify inserts a word break before subtest names beginning with a lowercase letter (0.00s)
291293
✔ Prettify is okay with test names not in the form of a sentence (0.00s)
292294
✔ Prettify keeps a trailing digit as part of an initialism (0.00s)
293295
✔ Prettify keeps numbers within a hyphenated word (0.00s)
296+
✔ Prettify keeps together digits in numbers that are standalone words (0.00s)
294297
✔ Prettify keeps together hyphenated words with initial capitals (0.00s)
295298
✔ Prettify keeps together hyphenated words with initialisms (0.00s)
296299
✔ Prettify knows that just test is a valid test name (0.00s)
297300
✔ Prettify preserves capitalisation of initialism when it is the first word (0.00s)
298301
✔ Prettify preserves capitalisation of initialisms such as PDF (0.00s)
299302
✔ Prettify preserves capitalisation of two-letter initialisms such as OK (0.00s)
303+
✔ Prettify preserves initialisms containing digits (0.00s)
304+
✔ Prettify preserves initialisms containing digits with two or more leading alpha characters (0.00s)
300305
✔ Prettify preserves longer all-caps words (0.00s)
301306
✔ Prettify recognises a dash followed by a digit as a negative number (0.00s)
302307
✔ Prettify renders subtest names without the slash, and with underscores replaced by spaces (0.00s)
@@ -308,7 +313,7 @@ github.com/bitfield/gotestdox:
308313
✔ Prettify treats consecutive underscores as a single word break (0.00s)
309314
✔ Prettify treats numbers as word separators (0.00s)
310315
✔ Prettify treats underscores as word breaks (0.00s)
311-
✔ Relevant is false for non pass fail events (0.00s)
316+
✔ Relevant is false for non test pass fail events (0.00s)
312317
✔ Relevant is true for test pass or fail events (0.00s)
313318
```
314319

fuzz_test.go

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//go:build go1.18
2+
3+
package gotestdox_test
4+
5+
import (
6+
"strings"
7+
"testing"
8+
"unicode"
9+
10+
"github.com/bitfield/gotestdox"
11+
)
12+
13+
func FuzzPrettify(f *testing.F) {
14+
for _, tc := range Cases {
15+
f.Add(tc.input)
16+
}
17+
f.Fuzz(func(t *testing.T, input string) {
18+
if len(input) > 0 && unicode.IsLower([]rune(input)[0]) {
19+
t.Skip()
20+
}
21+
got := gotestdox.Prettify(input)
22+
if got == "" {
23+
t.Skip()
24+
}
25+
if strings.ContainsRune(got, '_') {
26+
t.Errorf("%q: contains underscore %q", input, got)
27+
}
28+
if strings.ContainsRune(got, '/') {
29+
t.Errorf("%q: contains slash %q", input, got)
30+
}
31+
})
32+
}

gotestdox.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ func (td *TestDoxer) Filter() {
8484
}
8585
if event.Package != curPkg {
8686
if curPkg != "" {
87-
fmt.Fprintln(td.Stdout, curPkg)
87+
fmt.Fprintln(td.Stdout)
8888
}
8989
fmt.Fprintf(td.Stdout, "%s:\n", event.Package)
9090
curPkg = event.Package

gotestdox_test.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ func TestRelevantIsTrueForTestPassOrFailEvents(t *testing.T) {
7676
}
7777
}
7878

79-
func TestRelevantIsFalseForNonPassFailEvents(t *testing.T) {
79+
func TestRelevantIsFalseForNonTestPassFailEvents(t *testing.T) {
8080
t.Parallel()
8181
tcs := []gotestdox.Event{
8282
{
@@ -158,7 +158,7 @@ func TestFilterSetsOKToFalseIfAnyTestFails(t *testing.T) {
158158
}
159159
}
160160

161-
func TestFilterReturnsNotOKOnParsingError(t *testing.T) {
161+
func TestFilterSetsOKToFalseOnParsingError(t *testing.T) {
162162
t.Parallel()
163163
td := gotestdox.TestDoxer{
164164
Stdin: strings.NewReader("invalid"),
@@ -171,7 +171,7 @@ func TestFilterReturnsNotOKOnParsingError(t *testing.T) {
171171
}
172172
}
173173

174-
func TestExecGoTest_ReturnsOKWhenTestsPass(t *testing.T) {
174+
func TestExecGoTest_SetsOKToTrueWhenTestsPass(t *testing.T) {
175175
t.Parallel()
176176
path := newTempTestPath(t, passingTest)
177177
td := gotestdox.TestDoxer{
@@ -185,7 +185,7 @@ func TestExecGoTest_ReturnsOKWhenTestsPass(t *testing.T) {
185185
}
186186
}
187187

188-
func TestExecGoTest_ReturnsNotOKWhenTestsFail(t *testing.T) {
188+
func TestExecGoTest_SetsOKToFalseWhenTestsFail(t *testing.T) {
189189
t.Parallel()
190190
path := newTempTestPath(t, failingTest)
191191
td := gotestdox.TestDoxer{
@@ -199,7 +199,7 @@ func TestExecGoTest_ReturnsNotOKWhenTestsFail(t *testing.T) {
199199
}
200200
}
201201

202-
func TestExecGoTest_ReturnsNotOKWhenCommandErrors(t *testing.T) {
202+
func TestExecGoTest_SetsOKToFalseWhenCommandErrors(t *testing.T) {
203203
t.Parallel()
204204
td := gotestdox.TestDoxer{
205205
Stdout: io.Discard,

prettifier.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ func start(p *prettifier, r rune) stateFunc {
103103
case unicode.IsUpper(r):
104104
p.emitRune(r)
105105
return inWordUpper
106+
case r == '/':
107+
p.inSubTest = true
108+
return betweenWords
106109
default:
107110
return start
108111
}
@@ -117,6 +120,9 @@ func betweenWords(p *prettifier, r rune) stateFunc {
117120
case unicode.IsLower(r):
118121
p.emitRune(r)
119122
return inWordLower
123+
case unicode.IsDigit(r):
124+
p.emitRune(r)
125+
return inNumber
120126
case r == '_':
121127
p.seenUnderscore = true
122128
return betweenWords
@@ -179,7 +185,7 @@ func inInitialism(p *prettifier, r rune) stateFunc {
179185
func inWordUpper(p *prettifier, r rune) stateFunc {
180186
p.log("inWordUpper", p.curWord, string(r))
181187
switch {
182-
case unicode.IsUpper(r):
188+
case unicode.IsUpper(r), unicode.IsDigit(r):
183189
p.emitRune(r)
184190
return inInitialism
185191
case r == '_':
@@ -212,7 +218,7 @@ func inWordLower(p *prettifier, r rune) stateFunc {
212218
p.emitRune(r)
213219
return inWordUpper
214220
case unicode.IsDigit(r):
215-
if !strings.HasSuffix(p.curWord, "-") {
221+
if !strings.HasSuffix(p.curWord, "-") && !strings.HasSuffix(p.curWord, "=") {
216222
p.emitWord()
217223
}
218224
p.emitRune(r)

prettifier_test.go

+32-23
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@ package gotestdox_test
22

33
import (
44
"fmt"
5-
"strings"
65
"testing"
7-
"unicode"
86

97
"github.com/bitfield/gotestdox"
108
"github.com/google/go-cmp/cmp"
@@ -22,6 +20,13 @@ func TestPrettify(t *testing.T) {
2220
}
2321
}
2422

23+
func BenchmarkPrettify(b *testing.B) {
24+
input := "TestParseJSON_CorrectlyParsesASingleGoTestJSONOutputLine"
25+
for i := 0; i < b.N; i++ {
26+
_ = gotestdox.Prettify(input)
27+
}
28+
}
29+
2530
func ExamplePrettify() {
2631
input := "TestFoo/has_well-formed_output"
2732
fmt.Println(gotestdox.Prettify(input))
@@ -36,27 +41,6 @@ func ExamplePrettify_underscoreHint() {
3641
// HandleInput closes input after reading
3742
}
3843

39-
func FuzzPrettify(f *testing.F) {
40-
for _, tc := range Cases {
41-
f.Add(tc.input)
42-
}
43-
f.Fuzz(func(t *testing.T, input string) {
44-
if len(input) > 0 && unicode.IsLower([]rune(input)[0]) {
45-
t.Skip()
46-
}
47-
got := gotestdox.Prettify(input)
48-
if got == "" {
49-
t.Skip()
50-
}
51-
if strings.ContainsRune(got, '_') {
52-
t.Errorf("%q: contains underscore %q", input, got)
53-
}
54-
if strings.ContainsRune(got, '/') {
55-
t.Errorf("%q: contains slash %q", input, got)
56-
}
57-
})
58-
}
59-
6044
var Cases = []struct {
6145
name, input, want string
6246
}{
@@ -195,4 +179,29 @@ var Cases = []struct {
195179
input: "TestListObjects/FS-Test71",
196180
want: "List objects FS-test 71",
197181
},
182+
{
183+
name: "keeps together digits in numbers that are standalone words",
184+
input: "TestLex11",
185+
want: "Lex 11",
186+
},
187+
{
188+
name: "handles a test with no name, but with subtests",
189+
input: "Test/default/issue12839",
190+
want: "Default issue 12839",
191+
},
192+
{
193+
name: "does not break words when a digit follows an = sign",
194+
input: "TestUniformFactorial/n=3",
195+
want: "Uniform factorial n=3",
196+
},
197+
{
198+
name: "preserves initialisms containing digits",
199+
input: "TestS390XOperandParser",
200+
want: "S390X operand parser",
201+
},
202+
{
203+
name: "preserves initialisms containing digits with two or more leading alpha characters",
204+
input: "TestBC35A",
205+
want: "BC35A",
206+
},
198207
}

0 commit comments

Comments
 (0)