Skip to content

Add XML coverage support in multiple-files mode#248

Merged
MishaKav merged 6 commits intomainfrom
add-xml-coverage-support-in-multiline-mode
Feb 21, 2026
Merged

Add XML coverage support in multiple-files mode#248
MishaKav merged 6 commits intomainfrom
add-xml-coverage-support-in-multiline-mode

Conversation

@MishaKav
Copy link
Owner

Summary

  • Add XML coverage file support in multiple-files input, auto-detected by .xml extension
  • Allows mixing TXT and XML coverage formats in the same multi-file report (useful for monorepos)
  • Add safety check for XML coverage structure to prevent runtime errors
  • Bump version to 1.3.0

Closes #200

Test plan

  • npm test — unit tests for mixed TXT/XML multi-file coverage
  • npm run all — lint, format, build pass
  • Manual: verify PR comment renders correctly with mixed TXT/XML coverage

🤖 Generated with Claude Code

hayes0724 and others added 6 commits October 23, 2025 09:12
chore: setup tests for multi line with xml
Adds XML coverage file support alongside existing TXT in multiple-files input.
Auto-detects format by .xml extension, adds safety checks for XML coverage
structure, and includes tests and CI workflow.

Co-Authored-By: Eric Hayes <hayes0724@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Added auto-detection for XML coverage files by `.xml` extension.
- Enabled mixing of TXT and XML formats in multi-file reports, beneficial for monorepos.
- Implemented a safety check for XML coverage structure to prevent runtime errors.
- Removed obsolete CI workflow for multiline XML coverage.

Co-authored-by: Eric Hayes <hayes0724@users.noreply.github.com>
@github-actions
Copy link
Contributor

Coverage

Coverage Report
FileStmtsMissCoverMissing
functions/example_completed
   example_completed.py641970%33, 39–45, 48–51, 55–58, 65–70, 91–92
functions/example_manager
   example_manager.py441175%31–33, 49–55, 67–69
   example_static.py40295%60–61
functions/my_exampels
   example.py20200%1–31
functions/resources
   resources.py26260%1–37
TOTAL105573930% 

Tests Skipped Failures Errors Time
109 2 💤 1 ❌ 0 🔥 0.583s ⏱️

@MishaKav MishaKav requested a review from Copilot February 21, 2026 16:36
@coderabbitai
Copy link

coderabbitai bot commented Feb 21, 2026

Walkthrough

This change adds XML coverage file support to the multiple-files mode of Pytest Coverage Comment. Previously, the multiple-files feature only handled text-based coverage reports. The implementation now auto-detects XML coverage files by their .xml extension, allows mixing TXT and XML formats in the same multi-file report, and adapts output generation to handle both coverage types. Supporting changes include documentation updates, a version bump to 1.3.0, and a test validating the new functionality.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The description covers the key changes (XML support, mixing formats, safety checks, version bump) and includes test plan, but does not match the provided template structure. While informative, consider reformatting to explicitly match the template sections: 'What does this PR do?' and 'Checklist' with checkbox items.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately captures the main feature added: XML coverage support in multiple-files mode, directly addressing the primary change.
Linked Issues check ✅ Passed The PR successfully implements XML coverage file support in multiple-files mode with auto-detection by .xml extension, directly addressing issue #200's requirement.
Out of Scope Changes check ✅ Passed All changes are directly related to the PR objective: XML support in multiple-files (src/multiFiles.js), documentation updates (action.yml, CHANGELOG.md), tests (test/multiple-files.test.js), and version bump (package.json).
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch add-xml-coverage-support-in-multiline-mode

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@MishaKav MishaKav merged commit 09d4ea6 into main Feb 21, 2026
7 of 8 checks passed
@MishaKav MishaKav deleted the add-xml-coverage-support-in-multiline-mode branch February 21, 2026 16:41
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds support for XML coverage files in the multiple-files input mode, enabling monorepos to mix TXT and XML coverage formats in a single comment. The feature auto-detects XML coverage files by their .xml extension and routes them to the appropriate parser. The implementation also includes a new test file to verify the mixed-format functionality.

Changes:

  • Added XML coverage support in multiple-files mode with auto-detection by file extension
  • Extended getMultipleReport function to handle both TXT and XML coverage formats
  • Added unit test for mixed TXT/XML coverage reporting
  • Updated documentation to reflect new capability

Reviewed changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
test/multiple-files.test.js New test file verifying mixed TXT/XML coverage in multi-file mode
src/multiFiles.js Core implementation: auto-detects XML coverage by extension and routes to appropriate parser
package.json Version bump to 1.3.0 and added test script
dist/index.js Built distribution file with same changes as src/multiFiles.js
action.yml Updated documentation to explain TXT/XML support in multiple-files input
CHANGELOG.md Added release notes for version 1.3.0

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

const output = newOptions.covXmlFile
? getCoverageXmlReport(newOptions)
: getCoverageReport(newOptions);
core.setOutput('coverageHtml', output.html);
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The getCoverageXmlReport function can return null (when parsedXml is invalid) or an empty string (on error), which will cause a runtime error when accessing output.html on line 86. The getCoverageReport function always returns a valid object with html, coverage, color, and warnings properties, but getCoverageXmlReport does not follow the same pattern. Either getCoverageXmlReport should be updated to always return a valid object (like getCoverageReport does), or add a null check here before accessing output.html.

Suggested change
core.setOutput('coverageHtml', output.html);
const coverageHtml =
output && typeof output === 'object' && 'html' in output
? output.html
: '';
core.setOutput('coverageHtml', coverageHtml);

Copilot uses AI. Check for mistakes.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
test/multiple-files.test.js (1)

36-57: Test assertions don't verify per-source correctness.

The test only checks string presence across the whole table. It cannot distinguish whether TXT coverage was parsed as TXT and XML as XML. Consider adding at least one assertion that confirms the two rows are independently populated (e.g., count of :zzz: occurrences equals 2, one per row).

   assert.ok(table.includes(':stopwatch:'), 'Time emoji should be present');
+
+  // Both rows should have JUnit summary columns
+  const zzz = (table.match(/:zzz:/g) || []).length;
+  assert.strictEqual(zzz, 2, 'Each row should have its own :zzz: (skipped) column');
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/multiple-files.test.js` around lines 36 - 57, The test's assertions only
check global string presence and don't ensure per-source rows are populated
independently; update the test that calls getMultipleReport to verify per-row
correctness by asserting counts and row-specific content (e.g., assert that
occurrences of ':zzz:', ':x:', ':fire:', and ':stopwatch:' each equal 2 to
ensure both TXT and XML rows include those columns, and add assertions that the
'TXT Title' row contains TXT-specific values and the 'XML Title' row contains
XML-specific values), referencing getMultipleReport, 'TXT Title', 'XML Title',
and the emoji strings to locate where to add these checks.
package.json (1)

29-30: npm run all does not execute the new test suite.

The "all" script runs lint && format && build but not test. Running npm run all in CI will not catch test failures.

💡 Suggested fix
-    "all": "npm run lint && npm run format && npm run build",
+    "all": "npm run lint && npm run format && npm run build && npm test",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package.json` around lines 29 - 30, Update the package.json "all" script to
include running the test suite so CI runs tests; locate the "all" script entry
(currently "all": "npm run lint && npm run format && npm run build") and append
or insert the test step (invoke the existing "test" script name) so it executes
lint, format, build, and test in sequence.
src/multiFiles.js (1)

43-43: hasXmlReports is now ambiguous — rename to hasJunitReports.

Before this PR, "XML" meant JUnit XML. Now there are two XML types (covXmlFile for coverage XML, xmlFile for JUnit XML). The variable hasXmlReports checks l.xmlFile (JUnit XML), but its name now reads as "has XML coverage reports", which is the opposite of its meaning.

-    const hasXmlReports = lineReports.some((l) => l.xmlFile);
+    const hasJunitReports = lineReports.some((l) => l.xmlFile);

(And update the two uses at lines 50 and 104.)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/multiFiles.js` at line 43, Rename the ambiguous variable hasXmlReports to
hasJunitReports to reflect that it checks JUnit XML (lineReports.some(l =>
l.xmlFile)) and not coverage XML (covXmlFile); update the variable declaration
(currently const hasXmlReports = lineReports.some((l) => l.xmlFile)) and replace
all its uses (the two places that reference hasXmlReports later in this file) to
use hasJunitReports, and ensure no other logic is changed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/multiFiles.js`:
- Around line 83-86: The code assumes output.html exists but
getCoverageXmlReport can return null or empty string; update the block that
calls getCoverageXmlReport/getCoverageReport (the ternary producing output) to
handle falsy returns from getCoverageXmlReport: call the chosen function into a
local variable (e.g., output), then check that output is an object with an html
property before calling core.setOutput('coverageHtml', output.html), otherwise
provide a safe fallback (empty string or result from getCoverageReport) or throw
a clear error; reference getCoverageXmlReport, getCoverageReport, newOptions and
core.setOutput to locate where to add the null/empty guard.
- Around line 78-80: The current branch skips calling core.setOutput('warnings',
report.warnings) when internalOptions.covXmlFile is truthy, causing the warnings
output to be unset; ensure warnings is always emitted by setting
core.setOutput('warnings', String(report.warnings ?? 0)) (or explicitly '0')
either before/after the covXmlFile conditional or inside the covXmlFile branch
so that core.setOutput('warnings', ...) is invoked in all cases and downstream
consumers receive a numeric string.

---

Nitpick comments:
In `@package.json`:
- Around line 29-30: Update the package.json "all" script to include running the
test suite so CI runs tests; locate the "all" script entry (currently "all":
"npm run lint && npm run format && npm run build") and append or insert the test
step (invoke the existing "test" script name) so it executes lint, format,
build, and test in sequence.

In `@src/multiFiles.js`:
- Line 43: Rename the ambiguous variable hasXmlReports to hasJunitReports to
reflect that it checks JUnit XML (lineReports.some(l => l.xmlFile)) and not
coverage XML (covXmlFile); update the variable declaration (currently const
hasXmlReports = lineReports.some((l) => l.xmlFile)) and replace all its uses
(the two places that reference hasXmlReports later in this file) to use
hasJunitReports, and ensure no other logic is changed.

In `@test/multiple-files.test.js`:
- Around line 36-57: The test's assertions only check global string presence and
don't ensure per-source rows are populated independently; update the test that
calls getMultipleReport to verify per-row correctness by asserting counts and
row-specific content (e.g., assert that occurrences of ':zzz:', ':x:', ':fire:',
and ':stopwatch:' each equal 2 to ensure both TXT and XML rows include those
columns, and add assertions that the 'TXT Title' row contains TXT-specific
values and the 'XML Title' row contains XML-specific values), referencing
getMultipleReport, 'TXT Title', 'XML Title', and the emoji strings to locate
where to add these checks.

Comment on lines +78 to +80
if (!internalOptions.covXmlFile) {
core.setOutput('warnings', report.warnings);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

warnings output is silently unset when the first multiple-files entry uses XML coverage.

When covXmlFile is active for the first entry, core.setOutput('warnings', ...) is never called. Users referencing steps.<id>.outputs.warnings will receive an empty string instead of '0', which may break downstream numeric comparisons. Consider explicitly defaulting it:

           core.setOutput('color', report.color);
           if (!internalOptions.covXmlFile) {
             core.setOutput('warnings', report.warnings);
+          } else {
+            core.setOutput('warnings', '0');
           }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/multiFiles.js` around lines 78 - 80, The current branch skips calling
core.setOutput('warnings', report.warnings) when internalOptions.covXmlFile is
truthy, causing the warnings output to be unset; ensure warnings is always
emitted by setting core.setOutput('warnings', String(report.warnings ?? 0)) (or
explicitly '0') either before/after the covXmlFile conditional or inside the
covXmlFile branch so that core.setOutput('warnings', ...) is invoked in all
cases and downstream consumers receive a numeric string.

Comment on lines +83 to 86
const output = newOptions.covXmlFile
? getCoverageXmlReport(newOptions)
: getCoverageReport(newOptions);
core.setOutput('coverageHtml', output.html);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Potential TypeError if getCoverageXmlReport returns null or '' on the second call.

getCoverageXmlReport can return null (invalid file) or '' (catch path). Unlike getCoverageReport, which always returns an object, the XML path has no null guard before accessing .html on line 86.

While the second call is likely to succeed (first call already validated the file, only commit changes), the asymmetry is a risk:

-          core.setOutput('coverageHtml', output.html);
+          core.setOutput('coverageHtml', (output && output.html) || '');
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/multiFiles.js` around lines 83 - 86, The code assumes output.html exists
but getCoverageXmlReport can return null or empty string; update the block that
calls getCoverageXmlReport/getCoverageReport (the ternary producing output) to
handle falsy returns from getCoverageXmlReport: call the chosen function into a
local variable (e.g., output), then check that output is an object with an html
property before calling core.setOutput('coverageHtml', output.html), otherwise
provide a safe fallback (empty string or result from getCoverageReport) or throw
a clear error; reference getCoverageXmlReport, getCoverageReport, newOptions and
core.setOutput to locate where to add the null/empty guard.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

multiple-files support for "pytest-xml-coverage-path"

3 participants