SCANPY-248 Auto detect test code#318
Conversation
SummaryAdds automatic detection of test file paths from Python tooling configuration. When New CLI flag What reviewers should knowCore Logic: Start with Integration Point: Tests: Extensive unit tests in Config Chain: New property Watch For: The distinction between "found nothing" (return False, fall through) and "declared but all invalid" (return True, set disable flag). Also check Windows path handling in
|
0cb9ba3 to
dd7a4af
Compare
c7dee3a to
4150bcc
Compare
4150bcc to
f0bd90b
Compare
c31219c to
f53f7e5
Compare
1dff852 to
1cf9e30
Compare
1cf9e30 to
9d12b07
Compare
9d12b07 to
ce9f8f0
Compare
170d90e to
e41141b
Compare
Seppli11
left a comment
There was a problem hiding this comment.
Overall, the cahnge looks good. It's really cool to see that we're finally parsing settings from the pyproject.toml file and co. (Hopefully the python version is next 🤞 )
One thing I'm not sure about is if it makes sense to also have a heuristic based on the folders in the scanner. It seems to create quite a few strange places where, IMO, the outcome isn't that straight forward.
The other, more nitpicky thing, python_project_loader doesn't seem like an appropriate name for this module, given how it is used and how closely tight it usage is to the present of the test property.
Let me know if you want to discuss anything
| # Running python_project_loader unconditionally would emit confusing warnings about | ||
| # pytest config even when the result would be discarded. | ||
| if SONAR_TESTS not in resolved_properties: | ||
| resolved_properties.update(python_project_loader.load(base_dir)) |
There was a problem hiding this comment.
In a more holistic view, applying the properties from the python_project_loader only if sonar.tests is not set doesn't really make sense to me. If we for example extend the python_project_loader to also detect the python version, things become weird.
Maybe it could make sense renaming the module to python_project_test_source_loader or similar (maybe you find a catchier name 😅 )
| return _load_from_ini_file(base_dir, "setup.cfg", _SETUP_CFG_PYTEST_SECTION) | ||
|
|
||
|
|
||
| def _load_from_filesystem(base_dir: pathlib.Path) -> Optional[str]: |
There was a problem hiding this comment.
Does it make sense to add this heuristic here as well, given that sonar-python itself has a more extensive set of heuristics.
There was a problem hiding this comment.
I think the heuristic from sonar-python is a bit of a crutch in the sense that it will only disable rules and still report metrics based on the FileType, because we can't contradict the scanner for the file type classification.
This will reduce noise but ultimately still produce an "inconsistent" analysis.
Having it here makes the analysis more consistent because the rule execution is in sync with the metrics reporting. It's an argument to use pysonar instead of the generic sonar-scanner-cli because here, the manual setup of sonar.tests is truly optional (assuming what is inferred matches the user expectations).
There was a problem hiding this comment.
That is a good point. Maybe it would make sense to only fall back to the heuristic if the user hasn't set anything, rather than we haven't found a valid test folder
There was a problem hiding this comment.
In a way I'm wondering if analysis coming from pysonar shouldn't simply disable the heuristic by default?
There was a problem hiding this comment.
Maybe that would make the most sense. It would certainly simplify the flow chart of how the heuristics apply.
And, even in the case where they don't specify anything in their respective configuration files, the file based heuristic should still pick up most cases.
| self._wait_for_ce_completion(workdir) | ||
| return process | ||
|
|
||
| def _wait_for_ce_completion(self, workdir: pathlib.Path) -> None: |
There was a problem hiding this comment.
This method does a lot of automatic checks and fallbacks. Is this really necessary for a test?
| resp.raise_for_status() | ||
| return resp.json() | ||
|
|
||
| def get_latest_ce_task(self) -> Optional[dict]: |
There was a problem hiding this comment.
this seems to be never called. Same applies to search_projects and get_project_measures
| testpaths = [] | ||
| """, | ||
| ) | ||
| result = python_project_loader.load(Path(".")) |
There was a problem hiding this comment.
If we keep the heuristic, this could lead to a weird behavior where the pyrpoject.tol loader returned an empty set, while the file heuristic loader found a folder. This would now override what the user set
| self.fs.create_dir("tests") | ||
| # nonexistent/ is not on disk — only tests/ should be returned | ||
| result = python_project_loader.load(Path(".")) | ||
| self.assertEqual(result[SONAR_TESTS], "tests") |
There was a problem hiding this comment.
A similar issue could appear here, where for whatever reason, all the user specified tests are not valid paths. If the heuristic picks them up, we're overriding what the user explicitly told us.
There was a problem hiding this comment.
I made changes so that if we detect a legitimate attempt to set the test, even if invalid, we disable the test detection heuristic downstream.
| def test_load_from_pytest_ini(self): | ||
| self.fs.create_file( | ||
| "pytest.ini", | ||
| contents="[pytest]\ntestpaths = tests integration\n", |
There was a problem hiding this comment.
nitpick: multiline strings would be nicer
2429d5d to
ca83884
Compare
565dede to
c41788d
Compare
b1b6bf8 to
29971b5
Compare
7ec4848 to
3e0b7bf
Compare
Seppli11
left a comment
There was a problem hiding this comment.
Looks good. I think like this, it makes a lot of sense and seems IMO intuitive. Thanks for implementing this 😁
One thing, it would probably make sense to add the new parameter as a cli option, as well as running the generate_cli_documentation.py tool to regenerate the documentation.
| SONAR_WORKING_DIRECTORY: Key = "sonar.working.directory" | ||
| SONAR_SCM_FORCE_RELOAD_ALL: Key = "sonar.scm.forceReloadAll" | ||
| SONAR_MODULES: Key = "sonar.modules" | ||
| SONAR_PYTHON_TEST_FILE_HEURISTIC_DISABLED: Key = "sonar.python.testFileHeuristic.disabled" |
There was a problem hiding this comment.
This option should also be added to the configuration.cli module as an option, potentially as a switch
176edd8 to
c22a766
Compare
|




No description provided.