{"id":6427,"library":"pycobertura","title":"pycobertura","description":"pycobertura is a Python library and command-line tool for parsing Cobertura XML coverage reports. It can display, filter, and diff coverage reports, highlighting changes in coverage metrics between two reports. The current version is 4.1.0, and it maintains an active, moderate release cadence, with major versions typically aligning with Python version support or significant API changes.","status":"active","version":"4.1.0","language":"en","source_language":"en","source_url":"https://github.com/aconrad/pycobertura","tags":["coverage","cobertura","diff","testing","cli"],"install":[{"cmd":"pip install pycobertura","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"Required for parsing Cobertura XML reports efficiently.","package":"lxml","optional":false}],"imports":[{"symbol":"Cobertura","correct":"from pycobertura import Cobertura"},{"symbol":"diff","correct":"from pycobertura import diff"},{"symbol":"HtmlReporter","correct":"from pycobertura.reporters import HtmlReporter"}],"quickstart":{"code":"import io\nfrom pycobertura import Cobertura, diff\n\n# Example Cobertura XML content\ncobertura_xml_baseline = '''<?xml version=\"1.0\" ?>\n<coverage branches-covered=\"0\" branches-valid=\"0\" complexity=\"0\" line-rate=\"0.5\" lines-covered=\"1\" lines-valid=\"2\" timestamp=\"1678886400\" version=\"coverage 6.0.0\">\n    <sources>\n        <source>/path/to/project</source>\n    </sources>\n    <packages>\n        <package line-rate=\"0.5\" branch-rate=\"0\" complexity=\"0\" name=\"my_module\">\n            <classes>\n                <class name=\"my_file.py\" filename=\"my_module/my_file.py\" line-rate=\"0.5\" branch-rate=\"0\" complexity=\"0\">\n                    <methods/>\n                    <lines>\n                        <line number=\"1\" hits=\"1\"/>\n                        <line number=\"2\" hits=\"0\"/>\n                    </lines>\n                </class>\n            </classes>\n        </package>\n    </packages>\n</coverage>'''\n\ncobertura_xml_current = '''<?xml version=\"1.0\" ?>\n<coverage branches-covered=\"0\" branches-valid=\"0\" complexity=\"0\" line-rate=\"1.0\" lines-covered=\"2\" lines-valid=\"2\" timestamp=\"1678886500\" version=\"coverage 6.0.0\">\n    <sources>\n        <source>/path/to/project</source>\n    </sources>\n    <packages>\n        <package line-rate=\"1.0\" branch-rate=\"0\" complexity=\"0\" name=\"my_module\">\n            <classes>\n                <class name=\"my_file.py\" filename=\"my_module/my_file.py\" line-rate=\"1.0\" branch-rate=\"0\" complexity=\"0\">\n                    <methods/>\n                    <lines>\n                        <line number=\"1\" hits=\"1\"/>\n                        <line number=\"2\" hits=\"1\"/>\n                    </lines>\n                </class>\n            </classes>\n        </package>\n    </packages>\n</coverage>'''\n\n# Parse the Cobertura reports\n# Cobertura can take a filename (string) or a string containing the XML\nbaseline_report = Cobertura(cobertura_xml_baseline)\ncurrent_report = Cobertura(cobertura_xml_current)\n\nprint(f\"Baseline report line rate: {baseline_report.line_rate:.2f}\")\nprint(f\"Current report line rate: {current_report.line_rate:.2f}\")\n\n# Calculate the diff between the two reports\ndifferences = diff(baseline_report, current_report)\n\nprint(\"\\n--- Coverage Differences ---\")\nfor file_path, file_diff in differences.files.items():\n    print(f\"File: {file_path}\")\n    print(f\"  Line rate change: {file_diff.line_rate_change:.2f}\")\n    print(f\"  Lines covered change: {file_diff.lines_covered_change}\")\n    print(f\"  Lines valid change: {file_diff.lines_valid_change}\")\n\n# Access changes for specific lines if available\nif 'my_module/my_file.py' in differences.files:\n    file_lines_changes = differences.files['my_module/my_file.py'].lines\n    for line_number, status in file_lines_changes.items():\n        print(f\"  Line {line_number}: {status.name}\") # e.g., NO_CHANGE, COVERED, UNCOVERED_NEW","lang":"python","description":"This quickstart demonstrates how to parse Cobertura XML reports using the `Cobertura` class and then how to compute and display the differences in coverage between two reports using the `diff` function. It uses in-memory XML strings for simplicity, but `Cobertura` can also load directly from file paths."},"warnings":[{"fix":"Upgrade Python to 3.7 or newer, or pin `pycobertura<4.0.0` in your dependencies.","message":"Python 3.6 support was dropped in pycobertura v4.0.0. Users on Python 3.6 must remain on pycobertura < 4.0.0 or upgrade their Python interpreter.","severity":"breaking","affected_versions":">=4.0.0"},{"fix":"Instead of pre-parsing XML, pass the XML file path or the XML content string directly to `Cobertura('path/to/report.xml')` or `Cobertura('<xml>...</xml>')`.","message":"The `Cobertura` class constructor API changed significantly in v3.0.0. Previously, it expected a pre-parsed `lxml.etree._Element` object. Since v3.0.0, it expects either a filename string or a string containing the XML content directly.","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"Standardize the file paths in your Cobertura reports, e.g., by ensuring your coverage generation tool uses relative paths from a common root or applying path transformations before diffing.","message":"When diffing reports, ensure that the file paths referenced within the Cobertura XML (e.g., `<class filename=\"my_module/my_file.py\">`) are consistent between the two reports, or pycobertura may not correctly match files for comparison.","severity":"gotcha","affected_versions":"all"}],"env_vars":null,"last_verified":"2026-04-15T00:00:00.000Z","next_check":"2026-07-14T00:00:00.000Z"}