Skip to content
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

Consider unifying first-party, prop-based helper function names (like jClass, toStringFun) #522

Open
JakeWharton opened this issue Mar 19, 2024 · 13 comments · May be fixed by #537
Open

Consider unifying first-party, prop-based helper function names (like jClass, toStringFun) #522

JakeWharton opened this issue Mar 19, 2024 · 13 comments · May be fixed by #537

Comments

@JakeWharton
Copy link
Contributor

JakeWharton commented Mar 19, 2024

The current naming is mostly just the property name as the function name. There's kClass(), collection size()s, exception message().

This strategy doesn't work for toString() or hashCode(). They get "Fun" suffixes as toStringFun() and hashCodeFun(), respectively.

This ties in somewhat with #521, and it actually leans me towards that issue choosing "have" so that these could be "has"-prefixed.

assertThat(foo).hasKClass().isEqualTo(Foo::class)
assertThat(array).hasSize().isEqualTo(3)
assertThat(user).hasToString().isEqualTo("User[name=Alice]")
@grodin
Copy link
Contributor

grodin commented Mar 20, 2024

Once there's an agreement on how to resolve #521, happy to handle this

@evant
Copy link
Collaborator

evant commented Mar 25, 2024

There is a subtle distinction there, the 'has*' methods do an assertion themselves while the non-has methods can't fail on their own. One thing I'd want to avoid is someone doing assertThat(array).hasSize() by itself not realizing that it will never fail.

@grodin
Copy link
Contributor

grodin commented Mar 26, 2024

Perhaps "having" could help here, as it seems less like an assertion:

assertThat(list).havingSize()

feels less like a complete sentence.

@JakeWharton
Copy link
Contributor Author

I also think having pairs well with extracting, should we opt not to change it to something like eachHaving.

@grodin
Copy link
Contributor

grodin commented Mar 27, 2024

I also think having pairs well with extracting, should we opt not to change it to something like eachHaving.

Perhaps that's a useful general principle for this kind of thing; a method named with a verb which isn't an assertion should use the continuous ("ing") form of the verb.

That's almost certainly a premature abstraction, and wrong in the details, but I thought it was worth noting down.

@evant
Copy link
Collaborator

evant commented May 7, 2024

Hm, looking at the draft mr I'm not sure I'm convinced that adding a having prefix to everything is preferable to the status-quo. There are far more methods that the current pattern works for than it doesn't. I think it would still be reasonable to rename toStringFun and hashCodeFun to havingToString and havingHashCode respectively, but thinking it may be better to keep the rest the same. Thoughts?

@JakeWharton
Copy link
Contributor Author

JakeWharton commented May 7, 2024

What are your primary examples of occurrences you don't like?

@evant
Copy link
Collaborator

evant commented May 7, 2024

From a wider context we are introducing api churn. Which in-itself isn't a bad thing but does mean that there should be a good reason for it.

Let's take message() for example. We'd go from:

assertThat(exception)
    .message()
    .isNotNull()
    .matches(Regex(...))

to

assertThat(exception)
    .havingMessage()
    .isNotNull()
    .matches(Regex(...))

The first one is shorter and reads slightly better. Like it's not a huge difference but if we are going to change things it should be a more obvious win no?

@evant
Copy link
Collaborator

evant commented May 7, 2024

note: this was partially spurred on by #521 (comment), which also points out than androidx has started using a similar pattern in their truth extensions

@JakeWharton
Copy link
Contributor Author

I actually think the havingMessage one reads better, because every function call is in the form of verb-noun, either by itself or in conjunction with the supplied argument.

It produces "assert (that) exception having message is not null matches regex".

It also means that you can type ".having" to see all built-in transformations as well as complete to the lambda variation to do custom transforms.

@grodin
Copy link
Contributor

grodin commented May 20, 2024

FWIW, I agree with Jake. I think the consistency of all helper functions starting with "having" helps distinguish them.

@JakeWharton
Copy link
Contributor Author

Since prop was renamed to having, has there been any movement of opinion here?

I can send a PR if so.

@JakeWharton
Copy link
Contributor Author

There's definitely an inconsistency with these functions today. size() on a map will never fail, but key() on that same map can fail.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants