-
Notifications
You must be signed in to change notification settings - Fork 693
SONARCH-708, SONARJAVA-5497: Extend SonarJava CheckRegistrar API for registering custom file scanner hooks #5083
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
base: master
Are you sure you want to change the base?
Conversation
1a75e68
to
b6c30f1
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.
I think the change looks simple enough to integrated as-is, but there are a couple of questions I have left for you to look at.
In addition, I thin that he ticket attached to this PR should be a SONARJAVA ticket because this change implies a modification of the public API and should be properly documented as part of the release
@Test | ||
void empty_default_method_coverage() { | ||
var context = new CheckRegistrar.RegistrarContext(); | ||
assertDoesNotThrow(() -> context.registerCustomFileScanner(null, null)); |
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.
What are we testing here? Isn't the default implementation of registerCustomFileScanner
empty?
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.
Yes, but QG failed due to low coverage. Even if the method is empty, it must still be tested. So just making sure the method is there and can be called without issues is the best thing we can do here I think.
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.
Summary from our discussion:
- If we introduced a return value just for testing, then what we really would be testing is only that the method does not terminate abnormally. We wouldn't be testing any behavior. I.e., if the method returns
true
, this does not proof anything what the method does or does not do apart from returningtrue
. - Therefore, a return value only for the matter of testing an empty method is redundant. Normal termination is equivalent to the method not throwing an exception, so we can test that instead.
assertTrue(context.registerCustomFileScanner(null, null))
would look nicer in the test, but it does not justify modifying the API - If we add a return value, it must have a true semantical meaning, not be introduced only for the testing. What we could do: a return value
false
indicates that the registration failed. The registrar could then print a log message or something.
@@ -96,6 +97,12 @@ class Scanner implements JavaCheck { | |||
"register 3 instantiated test checks."); | |||
} | |||
|
|||
@Test | |||
void empty_default_method_coverage() { |
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.
To help understanding the intent of the test, it would help if the test a name in the form of an assertion (that should not be broken)
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.
The purpose of the method is just to get coverage for an empty default method (see the other comment). Naming the method registerCustomFileScanner_does_not_throw_exception
would satisfy your request, but still I think it doesn't capture well the purpose of the test. I renamed it to cover_empty_default_implementations
. Wdyt?
/** | ||
* Registers a custom file scanner not related to any rule or repository. | ||
*/ | ||
public void registerCustomFileScanner(RuleScope ruleScope, JavaFileScanner scanner) { |
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.
Nitpicking: Have we considered returning some value here? To test that something was added, we need to look into the internals of the Checkregistrar
implementation. It works here but does not promote good testing practices in the custom plugins downstream.
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 think we should stick to the pattern used in CheckRegistrar
and not be doing it different for a single method: all the register*
methods have a void
return type.
If we want to change that, I think it should be done in a separate ticket, because changing it for all methods would clearly go beyond the scope of this PR (and also break backwards compatibility on the bytecode level, because even though source code level compatibility does remain, the method signatures would change in the class files).
if (ruleScope != RuleScope.TEST) { | ||
mainChecks.add(scanner); | ||
} | ||
if (ruleScope != RuleScope.MAIN) { | ||
testChecks.add(scanner); | ||
} |
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.
Can we arrange these tests in a less clever but more explicit way?
if (ruleScope != RuleScope.TEST) { | |
mainChecks.add(scanner); | |
} | |
if (ruleScope != RuleScope.MAIN) { | |
testChecks.add(scanner); | |
} | |
if (ruleScope == RuleScope.MAIN || ruleScope == RuleScope.ALL) { | |
mainChecks.add(scanner); | |
} | |
if (ruleScope == RuleScope.TEST || ruleScope == RuleScope.ALL) { | |
testChecks.add(scanner); | |
} |
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.
Fixed.
if (ruleScope != RuleScope.TEST) { | ||
registerMainHook(scanner); | ||
} | ||
if (ruleScope != RuleScope.MAIN) { | ||
registerTestHook(scanner); | ||
} |
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.
If we change the implemetation in SonarComponents
, we might as well change it here
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.
Fixed.
b223127
to
c20a76d
Compare
|
I think what bothers me most is the need to test an empty method and the lack of guidance for what a good implementation of After discussing with @kaufco, it looks like we have 2 options to improve the current proposal.
My preference goes for option 2 because it enables us to write a test where we can implement a child class and test what the default behavior is. @Test
void registerCustomFileScanner_default_implementation_returns_expected_value() {
class Child extends CheckRegistrar.RegistrarContext {
// Nothing overridden here
}
var context = new Child();
assertThat(context.registerCustomFileScanner(null, null)).isEqualTo(EXPECTED_VALUE);
} |
c20a76d
to
e486513
Compare
e486513
to
e3731be
Compare
|
SONARCH-708