Skip to content

Replace testify assertions with custom testing helpers#159

Merged
hanzei merged 2 commits into
stretchr:masterfrom
emilien-puget:remove-testify
Oct 3, 2025
Merged

Replace testify assertions with custom testing helpers#159
hanzei merged 2 commits into
stretchr:masterfrom
emilien-puget:remove-testify

Conversation

@emilien-puget

@emilien-puget emilien-puget commented Sep 10, 2025

Copy link
Copy Markdown
Contributor

Summary

Replace testify assertions with custom testing helpers

Checklist

  • Tests are passing: task test
  • Code style is correct: task lint

@emilien-puget

Copy link
Copy Markdown
Contributor Author

@ccoVeille wdyt ?

@ccoVeille ccoVeille left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great idea @emilien-puget !!

cc @dolmen @brackendawson

Some remarks anyway

Comment thread std_assert_test.go Outdated
Comment on lines +247 to +249
// Allow formatting helpers similar to fmt in tests using fmt.Sprintf
var _ = fmt.Sprintf
var _ = runtime.NumCPU

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see a need for this.

I feel like you are forcing import. So symbols are available.

Why that ?

I'm not saying you are wrong. I'm saying I'm suspicious

Comment thread std_assert_test.go
Comment on lines +13 to +14
var assert nonfatal
var require fatal

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This idea is awesome !

I was like: WTF why removing testify imports everywhere. It won't work!

You got me, and I love the solution you found.

Comment thread std_assert_test.go Outdated
}
return true
}
func (a fatal) Equal(t *testing.T, expected, actual interface{}, msgAndArgs ...interface{}) bool {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an issue with all fatal methods.

Here I'm talking about a compatibility issue with testify that is pointless as you remove testify dependency.

But I have to mention it.

testify/require asserters don't return bool

So here (and everywhere) it should be this

Suggested change
func (a fatal) Equal(t *testing.T, expected, actual interface{}, msgAndArgs ...interface{}) bool {
func (a fatal) Equal(t *testing.T, expected, actual interface{}, msgAndArgs ...interface{}) {

Comment thread std_assert_test.go Outdated
msg = fmt.Sprintf(msg, msgAndArgs...)
}
t.Helper()
t.Errorf(msg)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
t.Errorf(msg)
t.Error(msg)

Comment thread std_assert_test.go Outdated
msg = fmt.Sprintf(msg, msgAndArgs...)
}
t.Helper()
t.Fatalf(msg)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
t.Fatalf(msg)
t.Fatal(msg)

@emilien-puget

emilien-puget commented Sep 10, 2025

Copy link
Copy Markdown
Contributor Author

Great idea @emilien-puget !!

cc @dolmen @brackendawson

Some remarks anyway

thanks for the review, i made changes based on your remarks

Comment thread std_assert_test.go
Comment on lines +15 to +30
func (nonfatal) fail(t *testing.T, msg string, msgAndArgs ...interface{}) bool {
if len(msgAndArgs) > 0 {
msg = fmt.Sprintf(msg, msgAndArgs...)
}
t.Helper()
t.Error(msg)
return false
}

func (fatal) fail(t *testing.T, msg string, msgAndArgs ...interface{}) {
if len(msgAndArgs) > 0 {
msg = fmt.Sprintf(msg, msgAndArgs...)
}
t.Helper()
t.Fatal(msg)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpicking here.

Usually t.Helper() call in on the first line of a method.

Suggested change
func (nonfatal) fail(t *testing.T, msg string, msgAndArgs ...interface{}) bool {
if len(msgAndArgs) > 0 {
msg = fmt.Sprintf(msg, msgAndArgs...)
}
t.Helper()
t.Error(msg)
return false
}
func (fatal) fail(t *testing.T, msg string, msgAndArgs ...interface{}) {
if len(msgAndArgs) > 0 {
msg = fmt.Sprintf(msg, msgAndArgs...)
}
t.Helper()
t.Fatal(msg)
}
func (nonfatal) fail(t *testing.T, msg string, msgAndArgs ...interface{}) bool {
t.Helper()
if len(msgAndArgs) > 0 {
msg = fmt.Sprintf(msg, msgAndArgs...)
}
t.Error(msg)
return false
}
func (fatal) fail(t *testing.T, msg string, msgAndArgs ...interface{}) {
t.Helper()
if len(msgAndArgs) > 0 {
msg = fmt.Sprintf(msg, msgAndArgs...)
}
t.Fatal(msg)
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does it changes something or is it more an idiomatic way of doing it ?

@ccoVeille ccoVeille Sep 10, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's clearly idiomatic, but for good reasons.

here you have calls to fmt.Sprintf which cannot call t.Error or t.Fail, so it would be OK for now.

But anyone who could come after you to update these lines, may add something that calls t.Error before the call to t.Helper a few line later. Then the line calling t.Errir would be the one reported.

Also, I thought about a possible panic, that might affect the way a test helper could react when something panic.
But I'm unsure how it would affect a test, assuming the panic is caught.

Anyway, fmt.Sprintf handles panics: an example could be a fmt.Stringer that would panic would be represented with PANIC: when passed as %s/%v to fmt.Sprintf

Do, yes. It's idiomatic and safer.

@emilien-puget

Copy link
Copy Markdown
Contributor Author

@hanzei wdyt ?

@hanzei

hanzei commented Sep 23, 2025

Copy link
Copy Markdown
Collaborator

Let me fix the CI issues first, and then I'll take a look.

@hanzei hanzei left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not too happy that we are losing some of the nicely styled output of testify with these changes, but I see the need to move away from testify.

LGTM 👍

@hanzei

hanzei commented Sep 23, 2025

Copy link
Copy Markdown
Collaborator

@emilien-puget @ccoVeille Are we good to merge the PR?

Comment thread std_assert_test.go
@@ -0,0 +1,238 @@
package objx_test

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a comment that mentions why this file exists: this is a reimplementation of a subset of Testify's API to break a cycle dependency with Testify.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i added some words about that

@hanzei
hanzei merged commit b152998 into stretchr:master Oct 3, 2025
6 checks passed
@hanzei

hanzei commented Oct 3, 2025

Copy link
Copy Markdown
Collaborator

Thank you very much @emilien-puget 🎉

@emilien-puget

Copy link
Copy Markdown
Contributor Author

@hanzei could we have a release/tag so we can update it on testify side ?

@hanzei

hanzei commented Oct 7, 2025

Copy link
Copy Markdown
Collaborator

@emilien-puget Done! https://github.com/stretchr/objx/releases/tag/v0.5.3

@ccoVeille

Copy link
Copy Markdown

For record, I suggested @alexandear to use your code in @chavacava codeberg project

https://codeberg.org/chavacava/garif/pulls/15#issuecomment-10961225

He liked your idea

ccoVeille added a commit to ccoVeille/testifail that referenced this pull request Feb 24, 2026
ccoVeille added a commit to ccoVeille/testifail that referenced this pull request Feb 24, 2026
ccoVeille added a commit to ccoVeille/testifail that referenced this pull request Feb 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants