@@ -84,6 +84,12 @@ def mock_parse(file_path):
8484 <line number="2" hits="0"/>
8585 </lines>
8686 </class>
87+ <class filename="app.py">
88+ <lines>
89+ <line number="3" hits="1"/>
90+ <line number="4" hits="0"/>
91+ </lines>
92+ </class>
8793 </classes>
8894 </package>
8995 </packages>
@@ -189,10 +195,10 @@ def test_parse_coverage_report_cobertura(self, mock_xml_tree, processor):
189195 """
190196 coverage = processor .parse_coverage_report ()
191197 assert len (coverage ) == 1 , "Expected coverage data for one file"
192- assert coverage ["app.py" ].covered_lines == [1 ], "Should list line 1 as covered"
193- assert coverage ["app.py" ].covered == 1 , "Should have 1 line as covered"
194- assert coverage ["app.py" ].missed_lines == [2 ], "Should list line 2 as missed"
195- assert coverage ["app.py" ].missed == 1 , "Should have 1 line as missed"
198+ assert coverage ["app.py" ].covered_lines == [1 , 3 ], "Should list lines 1 and 3 as covered"
199+ assert coverage ["app.py" ].covered == 2 , "Should have 2 line as covered"
200+ assert coverage ["app.py" ].missed_lines == [2 , 4 ], "Should list lines 2 and 4 as missed"
201+ assert coverage ["app.py" ].missed == 2 , "Should have 2 line as missed"
196202 assert coverage ["app.py" ].coverage == 0.5 , "Coverage should be 50 percent"
197203
198204class TestLcovProcessor :
@@ -272,9 +278,10 @@ def test_parse_xml_coverage_report_success(self, mocker):
272278 # Assert
273279 assert len (coverage_data ) == 1
274280 assert 'MyClass' in coverage_data
275- assert coverage_data ['MyClass' ].missed == 5
276- assert coverage_data ['MyClass' ].covered == 15
277- assert coverage_data ['MyClass' ].coverage == 0.75
281+ # should not include <counter type="LINE" missed="5" covered="15"/>
282+ assert coverage_data ['MyClass' ].missed == 0
283+ assert coverage_data ['MyClass' ].covered == 0
284+ assert coverage_data ['MyClass' ].coverage == 0
278285
279286 # Handle empty or malformed XML/CSV coverage reports
280287 def test_parse_empty_xml_coverage_report (self , mocker ):
@@ -301,6 +308,147 @@ def test_parse_empty_xml_coverage_report(self, mocker):
301308 assert coverage_data ['MyClass' ].covered == 0
302309 assert coverage_data ['MyClass' ].coverage == 0.0
303310
311+ def test_returns_empty_lists_and_float (self , mocker ):
312+ # Mocking the necessary methods
313+ mocker .patch (
314+ "cover_agent.coverage.processor.JacocoProcessor._extract_package_and_class_java" ,
315+ return_value = ("com.example" , "Example" ),
316+ )
317+ mocker .patch (
318+ "cover_agent.coverage.processor.JacocoProcessor._parse_jacoco_xml" ,
319+ return_value = ([], []),
320+ )
321+
322+ # Initialize the CoverageProcessor object
323+ coverage_processor = JacocoProcessor (
324+ file_path = "path/to/coverage.xml" ,
325+ src_file_path = "path/to/example.java" ,
326+ )
327+
328+ # Invoke the parse_coverage_report_jacoco method
329+ coverageData = coverage_processor .parse_coverage_report ()
330+
331+ # Assert the results
332+ assert coverageData ["Example" ].covered_lines == [], "Expected covered_lines to be an empty list"
333+ assert coverageData ["Example" ].missed_lines == [], "Expected missed_lines to be an empty list"
334+ assert coverageData ["Example" ].coverage == 0 , "Expected coverage percentage to be 0"
335+
336+ def test_parse_missed_covered_lines_jacoco_xml_no_source_file (self , mocker ):
337+ #, mock_xml_tree
338+ mocker .patch (
339+ "cover_agent.coverage.processor.JacocoProcessor._extract_package_and_class_java" ,
340+ return_value = ("com.example" , "MyClass" ),
341+ )
342+ xml_str = """<?xml version="1.0" encoding="UTF-8"?>
343+ <report>
344+ <package name="path/to">
345+ <sourcefile name="MyClass.java">
346+ <line nr="35" mi="0" ci="9" mb="0" cb="0"/>
347+ <line nr="36" mi="0" ci="1" mb="0" cb="0"/>
348+ <line nr="37" mi="0" ci="3" mb="0" cb="0"/>
349+ <line nr="38" mi="0" ci="9" mb="0" cb="0"/>
350+ <line nr="39" mi="1" ci="0" mb="0" cb="0"/>
351+ <line nr="40" mi="5" ci="0" mb="0" cb="0"/>
352+ <line nr="41" mi="9" ci="0" mb="0" cb="0"/>
353+ <counter type="INSTRUCTION" missed="53" covered="387"/>
354+ <counter type="BRANCH" missed="2" covered="6"/>
355+ <counter type="LINE" missed="9" covered="94"/>
356+ <counter type="COMPLEXITY" missed="5" covered="23"/>
357+ <counter type="METHOD" missed="3" covered="21"/>
358+ <counter type="CLASS" missed="0" covered="1"/>
359+ </sourcefile>
360+ </package>
361+ </report>"""
362+ mocker .patch (
363+ "xml.etree.ElementTree.parse" ,
364+ return_value = ET .ElementTree (ET .fromstring (xml_str ))
365+ )
366+ processor = JacocoProcessor ("path/to/coverage_report.xml" , "path/to/MySecondClass.java" )
367+
368+ # Action
369+ coverage_data = processor .parse_coverage_report ()
370+
371+ # Assert
372+ assert 'MySecondClass' not in coverage_data
373+
374+ def test_parse_missed_covered_lines_jacoco_xml (self , mocker ):
375+ #, mock_xml_tree
376+ mocker .patch (
377+ "cover_agent.coverage.processor.JacocoProcessor._extract_package_and_class_java" ,
378+ return_value = ("com.example" , "MyClass" ),
379+ )
380+ xml_str = """<report>
381+ <package name="path/to">
382+ <sourcefile name="MyClass.java">
383+ <line nr="35" mi="0" ci="9" mb="0" cb="0"/>
384+ <line nr="36" mi="0" ci="1" mb="0" cb="0"/>
385+ <line nr="37" mi="0" ci="3" mb="0" cb="0"/>
386+ <line nr="38" mi="0" ci="9" mb="0" cb="0"/>
387+ <line nr="39" mi="1" ci="0" mb="0" cb="0"/>
388+ <line nr="40" mi="5" ci="0" mb="0" cb="0"/>
389+ <line nr="41" mi="9" ci="0" mb="0" cb="0"/>
390+ <counter type="INSTRUCTION" missed="53" covered="387"/>
391+ <counter type="BRANCH" missed="2" covered="6"/>
392+ <counter type="LINE" missed="9" covered="94"/>
393+ <counter type="COMPLEXITY" missed="5" covered="23"/>
394+ <counter type="METHOD" missed="3" covered="21"/>
395+ <counter type="CLASS" missed="0" covered="1"/>
396+ </sourcefile>
397+ </package>
398+ </report>"""
399+ mocker .patch (
400+ "xml.etree.ElementTree.parse" ,
401+ return_value = ET .ElementTree (ET .fromstring (xml_str ))
402+ )
403+ processor = JacocoProcessor ("path/to/coverage_report.xml" , "path/to/MyClass.java" )
404+
405+ # Action
406+ coverage_data = processor .parse_coverage_report ()
407+
408+ # Assert
409+ assert "MyClass" in coverage_data
410+ assert coverage_data ["MyClass" ].missed_lines == [39 , 40 , 41 ]
411+ assert coverage_data ["MyClass" ].covered_lines == [35 , 36 , 37 , 38 ]
412+
413+ def test_parse_missed_covered_lines_kotlin_jacoco_xml (self , mocker ):
414+ #, mock_xml_tree
415+ mocker .patch (
416+ "cover_agent.coverage.processor.JacocoProcessor._extract_package_and_class_kotlin" ,
417+ return_value = ("com.example" , "MyClass" ),
418+ )
419+ xml_str = """<report>
420+ <package name="path/to">
421+ <sourcefile name="MyClass.kt">
422+ <line nr="35" mi="0" ci="9" mb="0" cb="0"/>
423+ <line nr="36" mi="0" ci="1" mb="0" cb="0"/>
424+ <line nr="37" mi="0" ci="3" mb="0" cb="0"/>
425+ <line nr="38" mi="0" ci="9" mb="0" cb="0"/>
426+ <line nr="39" mi="1" ci="0" mb="0" cb="0"/>
427+ <line nr="40" mi="5" ci="0" mb="0" cb="0"/>
428+ <line nr="41" mi="9" ci="0" mb="0" cb="0"/>
429+ <counter type="INSTRUCTION" missed="53" covered="387"/>
430+ <counter type="BRANCH" missed="2" covered="6"/>
431+ <counter type="LINE" missed="9" covered="94"/>
432+ <counter type="COMPLEXITY" missed="5" covered="23"/>
433+ <counter type="METHOD" missed="3" covered="21"/>
434+ <counter type="CLASS" missed="0" covered="1"/>
435+ </sourcefile>
436+ </package>
437+ </report>"""
438+ mocker .patch (
439+ "xml.etree.ElementTree.parse" ,
440+ return_value = ET .ElementTree (ET .fromstring (xml_str ))
441+ )
442+ processor = JacocoProcessor ("path/to/coverage_report.xml" , "path/to/MyClass.kt" )
443+
444+ # Action
445+ coverage_data = processor .parse_coverage_report ()
446+
447+ # Assert
448+ assert "MyClass" in coverage_data
449+ assert coverage_data ["MyClass" ].missed_lines == [39 , 40 , 41 ]
450+ assert coverage_data ["MyClass" ].covered_lines == [35 , 36 , 37 , 38 ]
451+
304452class TestDiffCoverageProcessor :
305453 # Successfully parse JSON diff coverage report and extract coverage data for matching file path
306454 def test_parse_coverage_report_with_matching_file (self , mocker ):
0 commit comments