-
Notifications
You must be signed in to change notification settings - Fork 17.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
proposal: testing: expose a constructor for *testing.T #28021
Comments
Consider making the function take a |
OH. thanks @acln0 that's what i was looking for, closing this issue. |
wait, you cannot implement testing.TB, due to an unexported |
When I've needed to write a fake testing.TB, I've just gone ahead and included an embedded type tb struct {
name string
mu sync.Mutex
output []string
skipped, failed bool
// The testing.TB interface has an unexported method "to prevent users implementing the
// interface and so future additions to it will not violate Go 1 compatibility."
//
// This may cause problems across Go versions, but let's ignore them and
// work around that restriction by embedding a T so we satisfy the unexported methods of the interface.
*testing.T
}
var _ testing.TB = (*tb)(nil)
func (t *tb) Error(args ...interface{}) {
t.Log(args...)
t.Fail()
}
func (t *tb) Errorf(format string, args ...interface{}) {
t.Logf(format, args...)
t.Fail()
}
func (t *tb) Fail() {
t.mu.Lock()
t.failed = true
t.mu.Unlock()
}
func (t *tb) FailNow() {
t.Fail()
runtime.Goexit()
}
func (t *tb) Failed() bool {
t.mu.Lock()
failed := t.failed
t.mu.Unlock()
return failed
}
func (t *tb) Fatal(args ...interface{}) {
t.Log(args...)
t.FailNow()
}
func (t *tb) Fatalf(format string, args ...interface{}) {
t.Logf(format, args...)
t.FailNow()
}
func (t *tb) Log(args ...interface{}) {
t.mu.Lock()
defer t.mu.Unlock()
t.output = append(t.output, fmt.Sprintln(args...))
}
func (t *tb) Logf(format string, args ...interface{}) {
t.mu.Lock()
defer t.mu.Unlock()
// Ensure message ends with newline.
if len(format) > 0 && format[len(format)-1] != '\n' {
format += "\n"
}
t.output = append(t.output, fmt.Sprintf(format, args...))
}
func (t *tb) Name() string {
return t.name
}
func (t *tb) Skip(args ...interface{}) {
t.Log(args...)
t.SkipNow()
}
func (t *tb) SkipNow() {
t.mu.Lock()
t.skipped = true
t.mu.Unlock()
runtime.Goexit()
}
func (t *tb) Skipf(format string, args ...interface{}) {
t.Logf(format, args...)
t.SkipNow()
}
func (t *tb) Skipped() bool {
t.mu.Lock()
skipped := t.skipped
t.mu.Unlock()
return skipped
}
func (t *tb) Helper() {} |
Another option is to have your function take a smaller interface than |
yess both of these solutions are great, thanks @mvdan and @mark-rushakoff 🙏🏽🙏🏽 I will just create my own interface and *testing.T will implement it. |
Can we expose a constructor that creates a minimal
*testing.T
? (..or even make T an interface)?I have some helpers which I use for ease of testing. e.g.
I was thinking about testing this Assert, by passing in a new
*testing.T
and checking ift.Failed()
but my code panics because T is unable to be initialized properly.The text was updated successfully, but these errors were encountered: