-
Notifications
You must be signed in to change notification settings - Fork 365
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
Refactored coverage processor in to class hierarchy #230
Refactored coverage processor in to class hierarchy #230
Conversation
PR-Agent was enabled for this repository. To continue using it, please link your git user with your CodiumAI identity here. PR Reviewer Guide 🔍Here are some key observations to aid the review process:
|
PR-Agent was enabled for this repository. To continue using it, please link your git user with your CodiumAI identity here. PR Code Suggestions ✨Explore these optional code suggestions:
|
8491408
to
a60c58e
Compare
a60c58e
to
cdd3a21
Compare
/review |
PR Reviewer Guide 🔍(Review updated until commit d6ec168)Here are some key observations to aid the review process:
|
f2fa10a
to
d6ec168
Compare
/review |
Persistent review updated to latest commit d6ec168 |
@mrT23 @EmbeddedDevops1 This is ready for a review. I would appreciate a review and meanwhile I might add more tests. |
* A new class hierarchy for processing coverage from different tools * New interface representing CoverageReport and CoverageData * A factory to create the appropriate coverage processor
d6ec168
to
7c6a7c8
Compare
cover_agent/coverage/processor.py
Outdated
self, | ||
diff_coverage_report_path: str, | ||
file_path: str, | ||
src_file_path: str, | ||
): | ||
super().__init__(file_path, src_file_path) | ||
self.diff_coverage_report_path = diff_coverage_report_path | ||
|
||
def parse_coverage_report(self) -> Dict[str, CoverageData]: | ||
""" | ||
Parses a JSON-formatted diff coverage report to extract covered lines, missed lines, | ||
and the coverage percentage for the specified src_file_path. | ||
Returns: | ||
Tuple[List[int], List[int], float]: A tuple containing lists of covered and missed lines, | ||
and the coverage percentage. | ||
""" | ||
with open(self.diff_coverage_report_path, "r") as file: | ||
report_data = json.load(file) | ||
|
||
# Create relative path components of `src_file_path` for matching | ||
src_relative_path = os.path.relpath(self.src_file_path) | ||
src_relative_components = src_relative_path.split(os.sep) | ||
|
||
# Initialize variables for covered and missed lines | ||
relevant_stats = None | ||
coverage = {} | ||
for file_path, stats in report_data["src_stats"].items(): | ||
# Split the JSON's file path into components | ||
file_path_components = file_path.split(os.sep) | ||
|
||
# Match if the JSON path ends with the same components as `src_file_path` | ||
if ( | ||
file_path_components[-len(src_relative_components) :] | ||
== src_relative_components | ||
): | ||
relevant_stats = stats | ||
break | ||
|
||
# If a match is found, extract the data | ||
if relevant_stats: | ||
covered_lines = relevant_stats["covered_lines"] | ||
violation_lines = relevant_stats["violation_lines"] | ||
coverage_percentage = ( | ||
relevant_stats["percent_covered"] / 100 | ||
) # Convert to decimal | ||
else: | ||
# Default values if the file isn't found in the report | ||
covered_lines = [] | ||
violation_lines = [] | ||
coverage_percentage = 0.0 | ||
|
||
coverage[self.file_path] = CoverageData(covered_lines=covered_lines, covered=len(covered_lines), missed_lines=violation_lines,missed=len(violation_lines), coverage=coverage_percentage) | ||
return coverage | ||
|
||
class CoverageReportFilter: | ||
def filter_report(self, report: CoverageReport, file_pattern: str) -> CoverageReport: | ||
filtered_coverage = { | ||
file: coverage | ||
for file, coverage in report.file_coverage.items() | ||
if file_pattern in file | ||
} | ||
total_lines = sum(len(cov.covered_lines) + len(cov.missed_lines) for cov in filtered_coverage.values()) | ||
total_coverage = (sum(len(cov.covered_lines) for cov in filtered_coverage.values()) / total_lines) if total_lines > 0 else 0.0 | ||
return CoverageReport(total_coverage = total_coverage, file_coverage=filtered_coverage) | ||
|
||
class CoverageProcessorFactory: | ||
"""Factory for creating coverage processors based on tool type.""" | ||
|
||
@staticmethod | ||
def create_processor( | ||
tool_type: str, | ||
report_path: str, | ||
src_file_path: str, | ||
diff_coverage_report_path: Optional[str] = None | ||
) -> CoverageProcessor: | ||
""" | ||
Creates appropriate coverage processor instance. | ||
|
||
Args: | ||
tool_type: Coverage tool type (cobertura/jacoco/lcov) | ||
report_path: Path to coverage report | ||
src_file_path: Path to source file | ||
|
||
Returns: | ||
CoverageProcessor instance | ||
|
||
Raises: | ||
ValueError: If invalid tool type specified | ||
""" | ||
processors = { | ||
'cobertura': CoberturaProcessor, | ||
'jacoco': JacocoProcessor, | ||
'lcov': LcovProcessor, | ||
'diff_cover_json': DiffCoverageProcessor | ||
} | ||
if tool_type.lower() not in processors: | ||
raise ValueError(f"Invalid coverage type specified: {tool_type}") | ||
if tool_type.lower() == 'diff_cover_json': | ||
return DiffCoverageProcessor(diff_coverage_report_path, report_path, src_file_path) | ||
return processors[tool_type.lower()](report_path, src_file_path) |
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.
@coderustic Can you add some inline comments to this code?
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 added documentation for the methods. Let me know if anything specific is required.
@qododavid @EmbeddedDevops1 If everything looks like appreciate if you can merge this. |
Sorry - last request: Need to update the |
* While earlier PR[qodo-ai#230] managed to breakdown processing code into a class hierarechy, there wasnt any changes made to the code. This PR brings in enhancements to coverage processing where coverage data is stored by entity (Class or File). * Coverage data is stored using a FQDN so that conflicts are taken care. This closes[qodo-ai#251] * Earlier PR broke the behaviour of the agent that only target file coverage is considered if the global coverage flag is not set by the user, this PR fixes it to bring back the original behaviour.
* While earlier PR[qodo-ai#230] managed to breakdown processing code into a class hierarechy, there wasnt any changes made to the code. This PR brings in enhancements to coverage processing where coverage data is stored by entity (Class or File). * Coverage data is stored using a FQDN so that conflicts are taken care. This closes[qodo-ai#251] * Earlier PR broke the behaviour of the agent that only target file coverage is considered if the global coverage flag is not set by the user, this PR fixes it to bring back the original behaviour.
* While earlier PR[qodo-ai#230] managed to breakdown processing code into a class hierarechy, there wasnt any changes made to the code. This PR brings in enhancements to coverage processing where coverage data is stored by entity (Class or File). * Coverage data is stored using a FQDN so that conflicts are taken care. This closes[qodo-ai#251] * Earlier PR broke the behaviour of the agent that only target file coverage is considered if the global coverage flag is not set by the user, this PR fixes it to bring back the original behaviour.
* Enhanced coverage processing (#2) * While earlier PR[#230] managed to breakdown processing code into a class hierarechy, there wasnt any changes made to the code. This PR brings in enhancements to coverage processing where coverage data is stored by entity (Class or File). * Coverage data is stored using a FQDN so that conflicts are taken care. This closes[#251] * Earlier PR broke the behaviour of the agent that only target file coverage is considered if the global coverage flag is not set by the user, this PR fixes it to bring back the original behaviour. * removed sample-reports * bump version
User description
** CoverageData & CoverageReport
via a factory
PR Type
enhancement, tests
Description
CoverageData
andCoverageReport
data classes.Changes walkthrough 📝
processor.py
Implement coverage processing with a new class hierarchy
cover_agent/coverage/processor.py
CoverageData
andCoverageReport
data classes.(Cobertura, Lcov, Jacoco).
test_processor.py
Add tests for coverage processor classes
tests/coverage/test_processor.py
CoverageProcessorFactory
andCoverageProcessor
.Lcov).
CoverageProcessor.py
Minor formatting adjustment
cover_agent/CoverageProcessor.py
test_CoverageProcessor.py
Remove unnecessary newline
tests/test_CoverageProcessor.py