Skip to content
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

Support the new JUnit XML format. #7265

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions news/2 Fixes/6990.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add support for the new JUnit XML format used by pytest 5.1+.
29 changes: 27 additions & 2 deletions src/client/testing/common/xUnitParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,11 @@ export class XUnitParser implements IXUnitParser {
) {
const data = await this.fs.readFile(outputXmlFile);

const parserResult = await parseXML(data) as { testsuite: TestSuiteResult };
updateTests(tests, parserResult.testsuite);
const parserResult = await parseXML(data);
const junitResults = getJunitResults(parserResult);
if (junitResults) {
updateTests(tests, junitResults);
}
}
}

Expand All @@ -80,6 +83,28 @@ async function parseXML(data: string): Promise<any> {
});
}

// Return the actual test results from the given data.
// tslint:disable-next-line:no-any
function getJunitResults(parserResult: any): TestSuiteResult | undefined {
// This is the newer JUnit XML format (e.g. pytest 5.1 and later).
const fullResults = parserResult as { testsuites: { testsuite: TestSuiteResult[] }};
if (!fullResults.testsuites) {
return (parserResult as { testsuite: TestSuiteResult }).testsuite;
}

const junitSuites = fullResults.testsuites.testsuite;
if (!Array.isArray(junitSuites)) {
throw Error('bad JUnit XML data');
}
if (junitSuites.length === 0) {
return;
}
if (junitSuites.length > 1) {
throw Error('got multiple XML results');
}
return junitSuites[0];
}

// Update "tests" with the given results.
function updateTests(
tests: Tests,
Expand Down
38 changes: 37 additions & 1 deletion src/test/testing/common/xUnitParser.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ suite('Testing - parse JUnit XML file', () => {
node.line = line;
}

test('success with single passing test', async () => {
test('legacy - success with single passing test', async () => {
const tests = createDeclaratively(`
./
test_spam.py
Expand Down Expand Up @@ -72,6 +72,42 @@ suite('Testing - parse JUnit XML file', () => {
fs.verifyAll();
});

test('success with single passing test', async () => {
const tests = createDeclaratively(`
./
test_spam.py
<Tests>
test_spam
`);
const expected = createDeclaratively(`
./
test_spam.py
<Tests>
test_spam P 0.001
`);
fixResult(
expected.testFunctions[0].testFunction,
'test_spam.py',
3
);
const filename = 'x/y/z/results.xml';
fs.setup(f => f.readFile(filename))
.returns(() => Promise.resolve(`
<?xml version="1.0" encoding="utf-8"?>
<testsuites>
<testsuite errors="0" failures="0" hostname="vm-dev-linux-desktop" name="pytest" skipped="0" tests="1" time="0.011" timestamp="2019-09-05T17:17:35.868863">
<testcase classname="test_spam.Tests" file="test_spam.py" line="3" name="test_spam" time="0.001">
</testcase>
</testsuite>
</testsuites>
`));

await parser.updateResultsFromXmlLogFile(tests, filename);

expect(tests).to.deep.equal(expected);
fs.verifyAll();
});

test('no discovered tests', async () => {
const tests: Tests = createEmptyResults();
const expected: Tests = createEmptyResults();
Expand Down