Skip to content

Commit f4013b9

Browse files
authored
feat: enabled reporter reuse (#131)
Signed-off-by: Tronje Krop <[email protected]>
1 parent c1b306c commit f4013b9

File tree

9 files changed

+251
-81
lines changed

9 files changed

+251
-81
lines changed

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,14 @@
4747

4848
## Introduction
4949

50-
Goal of the `testing` framework is to provide simple and efficient tools to for
50+
Goal of the `testing` framework is to provide simple common patterns for
5151
writing effective unit, component, and integration tests in [`go`][go].
5252

53-
To accomplish this, the `testing` framework provides a couple of extensions for
54-
[`go`][go]'s [`testing`][testing] package that support a simple setup of
55-
strongly isolated and parallel running unit test using [`gomock`][gomock] and/or
56-
[`gock`][gock] that work under various failure scenarios, e.g. panics, and even
57-
in the presence of spawned [`go`-routines][go-routines].
53+
To accomplish this, the `testing` framework provides a couple of extensions
54+
for [`go`][go]'s [`testing`][testing] package that support a simple setup of
55+
strongly isolated and parallel running unit tests using [`gomock`][gomock]
56+
and/or [`gock`][gock] that work under various failure scenarios and in the
57+
presence of spawned [`go`-routines][go-routines].
5858

5959
[go-routines]: <https://go.dev/tour/concurrency>
6060

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.0.44
1+
0.0.45

internal/mock/common_test.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -324,9 +324,20 @@ var (
324324
Results: []*Params{},
325325
Variadic: true,
326326
}, {
327-
Name: "Panic",
328-
Params: []*Params{{Name: "arg", Type: "any"}},
329-
Results: []*Params{},
327+
Name: "Log",
328+
Params: []*Params{
329+
{Name: "args", Type: "[]any"},
330+
},
331+
Results: []*Params{},
332+
Variadic: true,
333+
}, {
334+
Name: "Logf",
335+
Params: []*Params{
336+
{Name: "format", Type: "string"},
337+
{Name: "args", Type: "[]any"},
338+
},
339+
Results: []*Params{},
340+
Variadic: true,
330341
}}
331342

332343
methodsGoMockTestReporter = []*Method{{

test/caller_test.go

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,20 @@ type Caller struct {
2020
path string
2121
}
2222

23+
// Log is the caller reporter function to capture the callers file and line
24+
// number of the `Log` call.
25+
func (c *Caller) Log(_ ...any) {
26+
_, path, line, _ := runtime.Caller(1)
27+
c.path = path + ":" + strconv.Itoa(line)
28+
}
29+
30+
// Logf is the caller reporter function to capture the callers file and line
31+
// number of the `Logf` call.
32+
func (c *Caller) Logf(_ string, _ ...any) {
33+
_, path, line, _ := runtime.Caller(1)
34+
c.path = path + ":" + strconv.Itoa(line)
35+
}
36+
2337
// Error is the caller reporter function to capture the callers file and line
2438
// number of the `Error` call.
2539
func (c *Caller) Error(_ ...any) {
@@ -76,8 +90,8 @@ func (c *Caller) Panic(_ any) {
7690

7791
// getCaller implements the capturing logic for the callers file and line
7892
// number for the given call.
79-
func getCaller(call func(t test.Reporter)) string {
80-
t := test.New(&testing.T{}, test.Failure, false)
93+
func getCaller(call func(t test.Panicer)) string {
94+
t := test.New(&testing.T{}, false).Expect(test.Failure)
8195
mocks := mock.NewMocks(t)
8296
caller := mock.Get(mocks,
8397
func(*gomock.Controller) *Caller {
@@ -92,48 +106,56 @@ func getCaller(call func(t test.Reporter)) string {
92106
}
93107

94108
var (
109+
// CallerLog provides the file with line number of the `Log` call.
110+
CallerLog = getCaller(func(t test.Panicer) {
111+
t.Log("log")
112+
})
113+
// CallerLogf provides the file with line number of the `Logf` call.
114+
CallerLogf = getCaller(func(t test.Panicer) {
115+
t.Logf("%s", "log")
116+
})
95117
// CallerError provides the file with line number of the `Error` call.
96-
CallerError = getCaller(func(t test.Reporter) {
118+
CallerError = getCaller(func(t test.Panicer) {
97119
t.Error("fail")
98120
})
99121
// CallerErrorf provides the file with line number of the `Errorf` call.
100-
CallerErrorf = getCaller(func(t test.Reporter) {
122+
CallerErrorf = getCaller(func(t test.Panicer) {
101123
t.Errorf("%s", "fail")
102124
})
103125
// CallerFatal provides the file with line number of the `Fatal` call.
104-
CallerFatal = getCaller(func(t test.Reporter) {
126+
CallerFatal = getCaller(func(t test.Panicer) {
105127
t.Fatal("fail")
106128
})
107129
// CallerFatalf provides the file with line number of the `Fatalf` call.
108-
CallerFatalf = getCaller(func(t test.Reporter) {
130+
CallerFatalf = getCaller(func(t test.Panicer) {
109131
t.Fatalf("%s", "fail")
110132
})
111133
// CallerFail provides the file with line number of the `Fail` call.
112-
CallerFail = getCaller(func(t test.Reporter) {
134+
CallerFail = getCaller(func(t test.Panicer) {
113135
t.Fail()
114136
})
115137
// CallerFailNow provides the file with line number of the `FailNow` call.
116-
CallerFailNow = getCaller(func(t test.Reporter) {
138+
CallerFailNow = getCaller(func(t test.Panicer) {
117139
t.FailNow()
118140
})
119141
// CallerPanic provides the file with line number of the `FailNow` call.
120-
CallerPanic = getCaller(func(t test.Reporter) {
142+
CallerPanic = getCaller(func(t test.Panicer) {
121143
t.Panic("fail")
122144
})
123145

124146
// Generic source directory for caller path evaluation.
125147
SourceDir = test.Must(os.Getwd())
126148
// CallerTestError provides the file with the line number of the `Error`
127149
// call in the test context implementation.
128-
CallerTestError = path.Join(SourceDir, "context.go:352")
150+
CallerTestError = path.Join(SourceDir, "context.go:344")
129151
// CallerReporterErrorf provides the file with the line number of the
130152
// `Errorf` call in the test reporter/validator implementation.
131-
CallerReporterError = path.Join(SourceDir, "reporter.go:87")
153+
CallerReporterError = path.Join(SourceDir, "reporter.go:135")
132154

133155
// CallerTestErrorf provides the file with the line number of the `Errorf`
134156
// call in the test context implementation.
135-
CallerTestErrorf = path.Join(SourceDir, "context.go:370")
157+
CallerTestErrorf = path.Join(SourceDir, "context.go:362")
136158
// CallerReporterErrorf provides the file with the line number of the
137159
// `Errorf` call in the test reporter/validator implementation.
138-
CallerReporterErrorf = path.Join(SourceDir, "reporter.go:109")
160+
CallerReporterErrorf = path.Join(SourceDir, "reporter.go:158")
139161
)

test/context.go

Lines changed: 32 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import (
1616
// Test is a minimal interface for abstracting test methods that are needed to
1717
// setup an isolated test environment for GoMock and Testify.
1818
type Test interface { //nolint:interfacebloat // Minimal interface.
19+
// Embeds the basic test reporter interface.
20+
Reporter
1921
// Name provides the test name.
2022
Name() string
2123
// Helper declares a test helper function.
@@ -38,33 +40,13 @@ type Test interface { //nolint:interfacebloat // Minimal interface.
3840
SkipNow()
3941
// Skipped reports whether the test has been skipped.
4042
Skipped() bool
41-
// Log provides a logging function for the test.
42-
Log(args ...any)
43-
// Logf provides a logging function for the test.
44-
Logf(format string, args ...any)
45-
// Error handles a failure messages when a test is supposed to continue.
46-
Error(args ...any)
47-
// Errorf handles a failure messages when a test is supposed to continue.
48-
Errorf(format string, args ...any)
49-
// Fatal handles a fatal failure message that immediate aborts of the test
50-
// execution.
51-
Fatal(args ...any)
52-
// Fatalf handles a fatal failure message that immediate aborts of the test
53-
// execution.
54-
Fatalf(format string, args ...any)
55-
// Fail handles a failure message that immediate aborts of the test
56-
// execution.
57-
Fail()
58-
// FailNow handles fatal failure notifications without log output that
59-
// aborts test execution immediately.
60-
FailNow()
6143
// Failed reports whether the test has failed.
6244
Failed() bool
6345
// Cleanup is a function called to setup test cleanup after execution.
6446
Cleanup(cleanup func())
6547
}
6648

67-
// Cleanuper defines an interface to add a custom mehtod that is called after
49+
// Cleanuper defines an interface to add a custom method that is called after
6850
// the test execution to cleanup the test environment.
6951
type Cleanuper interface {
7052
Cleanup(cleanup func())
@@ -80,7 +62,7 @@ func Run(expect Expect, test Func) func(*testing.T) {
8062
return func(t *testing.T) {
8163
t.Helper()
8264

83-
New(t, expect, Parallel).Run(test)
65+
New(t, Parallel).Expect(expect).Run(test)
8466
}
8567
}
8668

@@ -91,7 +73,7 @@ func RunSeq(expect Expect, test Func) func(*testing.T) {
9173
return func(t *testing.T) {
9274
t.Helper()
9375

94-
New(t, expect, !Parallel).Run(test)
76+
New(t, !Parallel).Expect(expect).Run(test)
9577
}
9678
}
9779

@@ -102,7 +84,7 @@ func InRun(expect Expect, test Func) Func {
10284
return func(t Test) {
10385
t.Helper()
10486

105-
New(t, expect, !Parallel).Run(test)
87+
New(t, !Parallel).Expect(expect).Run(test)
10688
}
10789
}
10890

@@ -123,14 +105,14 @@ type Context struct {
123105
}
124106

125107
// New creates a new minimal isolated test context based on the given test
126-
// context with the given expectation. The parent test context is used to
127-
// delegate methods calls to the parent context to propagate test results.
128-
func New(t Test, expect Expect, parallel bool) *Context {
108+
// context with. The parent test context is used to delegate methods calls
109+
// to the parent context to propagate test results.
110+
func New(t Test, parallel bool) *Context {
129111
if tx, ok := t.(*Context); ok {
130112
return &Context{
131113
t: tx, wg: tx.wg,
132114
deadline: tx.deadline,
133-
expect: expect,
115+
expect: true,
134116
parallel: parallel,
135117
}
136118
}
@@ -142,11 +124,23 @@ func New(t Test, expect Expect, parallel bool) *Context {
142124
deadline, _ := t.Deadline()
143125
return deadline
144126
}(t),
145-
expect: expect,
127+
expect: true,
146128
parallel: parallel,
147129
}
148130
}
149131

132+
// Expect sets up a new test outcome.
133+
func (t *Context) Expect(expect Expect) *Context {
134+
t.t.Helper()
135+
136+
t.mu.Lock()
137+
defer t.mu.Unlock()
138+
139+
t.expect = expect
140+
141+
return t
142+
}
143+
150144
// Timeout sets up an individual timeout for the test. This does not affect the
151145
// global test timeout or a pending parent timeout that may abort the test, if
152146
// the given duration is exceeding the timeout. A negative or zero duration is
@@ -325,6 +319,9 @@ func (t *Context) Log(args ...any) {
325319
t.t.Helper()
326320

327321
t.t.Log(args...)
322+
if t.reporter != nil {
323+
t.reporter.Log(args...)
324+
}
328325
}
329326

330327
// Logf delegates request to the parent context. It provides a logging function
@@ -333,6 +330,9 @@ func (t *Context) Logf(format string, args ...any) {
333330
t.t.Helper()
334331

335332
t.t.Logf(format, args...)
333+
if t.reporter != nil {
334+
t.reporter.Logf(format, args...)
335+
}
336336
}
337337

338338
// Error handles failure messages where the test is supposed to continue. On
@@ -466,7 +466,9 @@ func (t *Context) Panic(arg any) {
466466
stack := regexPanic.Split(string(debug.Stack()), -1)
467467
t.t.Fatalf("panic: %v\n%s\n%s", arg, stack[0], stack[1])
468468
} else if t.reporter != nil {
469-
t.reporter.Panic(arg)
469+
if reporter, ok := t.reporter.(Panicer); ok {
470+
reporter.Panic(arg)
471+
}
470472
}
471473
runtime.Goexit()
472474
}

test/context_test.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ func TestContext(t *testing.T) {
7575
mock.NewMocks(t).Expect(param.setup)
7676

7777
// When
78-
test.New(t, test.Success, !test.Parallel).
79-
Run(param.test)
78+
test.New(t, !test.Parallel).
79+
Expect(test.Success).Run(param.test)
8080
}))
8181
}
8282
}
@@ -129,8 +129,8 @@ func TestCleanup(t *testing.T) {
129129
t.Cleanup(func() { wg.Wait() })
130130

131131
// When
132-
test.New(t, test.Success, test.Parallel).
133-
Run(param.test)
132+
test.New(t, test.Parallel).
133+
Expect(test.Success).Run(param.test)
134134

135135
// Then
136136
defer wg.Done()
@@ -208,11 +208,11 @@ func TestContextParallel(t *testing.T) {
208208
}
209209

210210
// When
211-
test.New(t, test.Success, param.parallel).
212-
Run(func(t test.Test) {
213-
mock.NewMocks(t).Expect(param.setup)
214-
param.during(t)
215-
})
211+
test.New(t, param.parallel).
212+
Expect(test.Success).Run(func(t test.Test) {
213+
mock.NewMocks(t).Expect(param.setup)
214+
param.during(t)
215+
})
216216
}))
217217
}
218218
}
@@ -273,7 +273,7 @@ func TestDeadline(t *testing.T) {
273273
Run(func(t test.Test, param DeadlineParams) {
274274
mock.NewMocks(t).Expect(param.expect)
275275

276-
test.New(t, !param.failure, !test.Parallel).
276+
test.New(t, !test.Parallel).Expect(!param.failure).
277277
Timeout(param.time).StopEarly(param.early).
278278
Run(func(t test.Test) {
279279
// When

0 commit comments

Comments
 (0)