-
Notifications
You must be signed in to change notification settings - Fork 688
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
SONARJAVA-5256 Fix false positives on S2699 for AssertJ assertions #5008
Conversation
a9a9958
to
de36286
Compare
java-checks/src/main/java/org/sonar/java/checks/helpers/UnitTestUtils.java
Outdated
Show resolved
Hide resolved
This adds a test with a call to AssertJ's BDDAssertions.thenNoException().isThrownBy(...) which is currently a false positive for rule S2699 (Tests should include assertions). This also adds a second example with isTrue() call on some AssertJ *Assert class.
90e6217
to
5a65981
Compare
@VisibleForTesting | ||
static final Pattern ASSERTJ_ASSERTION_METHODS_PATTERN = Pattern.compile( | ||
"(allMatch|assert|contains|doesNot|has|is|returns|satisfies)([A-Z].*)?"); |
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.
Sorry, I didn't look enough carefully during the first review. I forgot to suggest:
- Try to move computation in the static field as much as possible (executed only once) instead of during each method invocation (executed millions of times).
So I would call asMatchPredicate()
in the static field initialization:
@VisibleForTesting | |
static final Pattern ASSERTJ_ASSERTION_METHODS_PATTERN = Pattern.compile( | |
"(allMatch|assert|contains|doesNot|has|is|returns|satisfies)([A-Z].*)?"); | |
@VisibleForTesting | |
static final Predicate<String> ASSERTJ_ASSERTION_METHODS_PREDICATE = Pattern.compile( | |
"(allMatch|assert|contains|doesNot|has|is|returns|satisfies)([A-Z].*)?").asMatchPredicate(); |
- Never use the
String#matches(String)
that will call several timesPattern.compile
.
We could have the following predicate:
private static final Pattern ASSERTJ_ASSERTION_CLASSNAME_PATTERN = Pattern.compile(
"org\\.assertj\\.core\\.api\\.[a-zA-Z]+Assert");
private static final Predicate<Type> ASSERTJ_ASSERTION_TYPE_PREDICATE =
type -> ASSERTJ_ASSERTION_CLASSNAME_PATTERN.matcher(type.fullyQualifiedName()).matches();
So we can replace:
MethodMatchers.create().ofType(type -> type.fullyQualifiedName().matches("org\\.assertj\\.core\\.api\\.[a-zA-Z]+Assert"))
with
MethodMatchers.create().ofType(ASSERTJ_ASSERTION_TYPE_PREDICATE)
5a65981
to
dbddf32
Compare
The previous conditions were too restrictive and there are many assertion methods in AssertJ. They generally follow the patterns that are described here. Note that this introduces a false negative in autoscan tests. Co-authored-by: Alban Auzeill <alban.auzeill@sonarsource.com>
dbddf32
to
9b620e1
Compare
Quality Gate passedIssues Measures |
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.
Thank you for the changes!
SONARJAVA-5256
There are many methods that can be used to write assertions with AssertJ. The previous pattern was only recognizing a couple of assertJ classes.
With this PR we generalize the pattern for recognizing AssertJ assertion methods so that it applies to many of these classes.