-
Notifications
You must be signed in to change notification settings - Fork 39
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
Introduce assorted AssertJ templates #37
Introduce assorted AssertJ templates #37
Conversation
AssertJMapTemplates
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a couple of questions but LGTM 👍
@BeforeTemplate | ||
AbstractLongAssert<?> before(long number) { | ||
return assertThat(number % 2).isEqualTo(1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just checking, do we need to check also the boxed variant of all of these or are they covered?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good one!
Refaster does autoboxing for us when it is trying to match. You can turn that off by using @NoAutoboxing, see a check for that here. When the type of a variable is going to be inferred, there is a resolution phase where this method is called.
Let's add test cases to make it clear that this is also included! Pushing something in a bit.
@BeforeTemplate | ||
AbstractMapAssert<?, ?, K, V> before(AbstractMapAssert<?, ?, K, V> mapAssert, K key, V value) { | ||
return mapAssert.containsExactlyInAnyOrderEntriesOf(ImmutableMap.of(key, value)); | ||
} | ||
|
||
@AfterTemplate | ||
AbstractMapAssert<?, ?, K, V> after(AbstractMapAssert<?, ?, K, V> mapAssert, K key, V value) { | ||
return mapAssert.containsOnly(Map.entry(key, value)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure I'm a fan of this rule, and special cases for singletons in general 🤔
IMO it leads to non-uniform assertions, for example my OCD is triggered by this:
assertThat(obj.getA()).containsOnly(Map.entry("1", 1));
assertThat(obj.getB()).containsExactlyInAnyOrderEntriesOf(ImmutableMap.of("2", 2, "3", 3));
I think I would prefer using the multi case as the default, so:
assertThat(obj.getA()).containsExactlyInAnyOrderEntriesOf(ImmutableMap.of("1", 1));
assertThat(obj.getB()).containsExactlyInAnyOrderEntriesOf(ImmutableMap.of("2", 2, "3", 3));
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Proposing something else now, PTAL 😄. @EnricSala @werli
In many other cases (e.g. for Lists and Sets) we do something similar to: containsExactlyInAnyOrderEntriesOf
.
When we know there is only one element, we generally make the assertion stronger by ommiting the InAnyOrder
part, such that we can also verify that it is in "in order". In the case of the Map we can use the containsExactlyEntriesOf
which: Verifies that the actual map contains only the entries of the given map and nothing else, *in order*.
What do you guys think of this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In many other cases (e.g. for Lists and Sets) we do something similar to: containsExactlyInAnyOrderEntriesOf.
This is what I'm not sure I agree with 🤔 having special cases for the singletons leads to assertions looking different, and if I need to make a change where a test is now supposed to return more elements then I need to make even more changes. Would be curious to the reasoning to better understand why not just use the multi-element form everywhere :)
When we know there is only one element, we generally make the assertion stronger by ommiting the InAnyOrder part, such that we can also verify that it is in "in order".
Just for my understanding, if we expect to find only one element anyway, why does it matter that we omit the InAnyOrder
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mention good points here.
if I need to make a change where a test is now supposed to return more elements then I need to make even more changes.
Yeah, that is indeed true.
Would be curious to the reasoning to better understand why not just use the multi-element form everywhere :)
To be frank, I consulted @Stephan202 about this and I think it is good to tag him so he can explain it in his words 😛.
Anyway, I'm going to give it a try and explain some parts of his reasoning (makes at least a good practice for me):
To start, the method name with InAnyOrder
is unnecessary long for the single element case as it does not add any information about what is being asserted. So in a way, it obfuscates the (intention of the) code.
Feel like how I'm explaining it doesn't make a strong case 😅.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I couldn't add anything to Enric's nice comments.
Nice to see these getting added. 👍
} | ||
|
||
@BeforeTemplate | ||
AbstractIntegerAssert<?> before(short number) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ai, this one needs to be a AbstractShortAssert
...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was wrong; the isEqualTo(1)
returns a AbstractIntegerAssert
, so in this case it is correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, I don't have anything extra to add other than the other discussions about the map assertions :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice 👍 Got one question and one edge case to consider.
...rone-contrib/src/main/java/tech/picnic/errorprone/refastertemplates/AssertJMapTemplates.java
Show resolved
Hide resolved
...rone-contrib/src/main/java/tech/picnic/errorprone/refastertemplates/AssertJMapTemplates.java
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the answers! 👍 LGTM.
Suggested commit message:
|
This is for `byte`, `int`, `long` and `short`.
ddbf8c7
to
0e42b2c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rebased and added a commit.
Tweaked suggested commit message:
Introduce assorted AssertJ Refaster templates (#37)
(The fact that one of the files is new doesn't seem so relevant.)
@mussatto anything else from your side? :)
} | ||
|
||
@AfterTemplate | ||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS) | |
@UseImportPolicy(STATIC_IMPORT_ALWAYS) |
return ImmutableSet.of( | ||
assertThat((byte) 1 % 2).isEqualTo(1), | ||
assertThat(Byte.valueOf((byte) 1) % 2).isEqualTo(1), | ||
assertThat((int) 1 % 2).isEqualTo(1), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
int
is the default.
assertThat((int) 1 % 2).isEqualTo(1), | |
assertThat(1 % 2).isEqualTo(1), |
assertThat(Byte.valueOf((byte) 1) % 2).isEqualTo(1), | ||
assertThat((int) 1 % 2).isEqualTo(1), | ||
assertThat(Integer.valueOf(1) % 2).isEqualTo(1), | ||
assertThat((long) 1 % 2).isEqualTo(1), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assertThat((long) 1 % 2).isEqualTo(1), | |
assertThat(1L % 2).isEqualTo(1), |
assertThat((int) 1 % 2).isEqualTo(1), | ||
assertThat(Integer.valueOf(1) % 2).isEqualTo(1), | ||
assertThat((long) 1 % 2).isEqualTo(1), | ||
assertThat(Long.valueOf(1L) % 2).isEqualTo(1), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assertThat(Long.valueOf(1L) % 2).isEqualTo(1), | |
assertThat(Long.valueOf(1) % 2).isEqualTo(1), |
@@ -221,4 +225,60 @@ private AssertJNumberTemplates() {} | |||
return numberAssert.isNotNegative(); | |||
} | |||
} | |||
|
|||
static final class AssertThatIsOdd { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Related to a discussion in another PR: I suppose this should be AssertThatNumberIsOdd
. One rule could be to identify method invocations comprising multiple overloads, and to add parameter type(s) in those cases.
|
||
@AfterTemplate | ||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS) | ||
NumberAssert<?, ?> after(Integer number) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can just use long
here :)
@BeforeTemplate | ||
AbstractIntegerAssert<?> before(byte number) { | ||
return assertThat(number % 2).isEqualTo(1); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this calls assertThat(int)
, and since Refaster is smart enough to match byte
to int
, we can leave out this case. Same for short
below.
Changes LGTM. |
AssertJMapTemplates
assertThat(string).{matches,doesNotMatch}(regex);
assertThat(number % 2).isEqualTo({0,1});