fix(cli): use path name for classname in JUnit reports instead of request URL (#8169)

* fix: 3123 CLI JUnit Report: classname Uses Request URL Instead of Request Name

* fix: update classname in JUnit report to use request path instead of name

* fix: update testcase classname in JUnit report to use request path instead of request name

* fix: update JUnit report classname to use API paths instead of collection paths

* fix: update classname in JUnit report to use backslashes for Windows compatibility

* fix: update JUnit report file paths to use API paths instead of mock paths
This commit is contained in:
sharan-bruno
2026-06-09 15:58:18 +05:30
committed by GitHub
parent 240826ebc1
commit 13a48a256f
6 changed files with 92 additions and 64 deletions

View File

@@ -1,6 +1,7 @@
const os = require('os');
const fs = require('fs');
const xmlbuilder = require('xmlbuilder');
const { stripExtension } = require('../utils/filesystem');
const makeJUnitOutput = async (results, outputPath) => {
const output = {
@@ -15,6 +16,7 @@ const makeJUnitOutput = async (results, outputPath) => {
const testCount = result.testResults ? result.testResults.length : 0;
const postResponseTestCount = result.postResponseTestResults ? result.postResponseTestResults.length : 0;
const totalTests = assertionTestCount + preRequestTestCount + testCount + postResponseTestCount;
const classname = stripExtension(result.path);
const suite = {
'@name': result.name,
@@ -34,7 +36,7 @@ const makeJUnitOutput = async (results, outputPath) => {
const testcase = {
'@name': `${assertion.lhsExpr} ${assertion.rhsExpr}`,
'@status': assertion.status,
'@classname': result.request.url,
'@classname': classname,
'@time': (result.runDuration / totalTests).toFixed(3)
};
@@ -52,7 +54,7 @@ const makeJUnitOutput = async (results, outputPath) => {
const testcase = {
'@name': test.description,
'@status': test.status,
'@classname': result.request.url,
'@classname': classname,
'@time': (result.runDuration / totalTests).toFixed(3)
};
@@ -70,7 +72,7 @@ const makeJUnitOutput = async (results, outputPath) => {
const testcase = {
'@name': test.description,
'@status': test.status,
'@classname': result.request.url,
'@classname': classname,
'@time': (result.runDuration / totalTests).toFixed(3)
};
@@ -88,7 +90,7 @@ const makeJUnitOutput = async (results, outputPath) => {
const testcase = {
'@name': test.description,
'@status': test.status,
'@classname': result.request.url,
'@classname': classname,
'@time': (result.runDuration / totalTests).toFixed(3)
};
@@ -110,7 +112,7 @@ const makeJUnitOutput = async (results, outputPath) => {
{
'@name': 'Test suite has no errors',
'@status': 'fail',
'@classname': result.request.url,
'@classname': classname,
'@time': result.runDuration.toFixed(3),
'error': [{ '@type': 'error', '@message': result.error }]
}

View File

@@ -103,6 +103,36 @@ describe('makeJUnitOutput', () => {
expect(failcase.failure[0]['@type']).toBe('failure');
});
it('should use the request path as the testcase classname instead of the request url', () => {
const results = [
{
name: '1st API',
path: 'f1/1st API.bru',
test: {
filename: 'f1/1st API.bru'
},
request: {
method: 'GET',
url: 'https://ima.test'
},
testResults: [
{
description: 'Status is 200',
status: 'pass'
}
],
runDuration: 1.2345678
}
];
makeJUnitOutput(results, '/tmp/testfile.xml');
const junit = xmlbuilder.create.mock.calls[0][0];
const testcase = junit.testsuites.testsuite[0].testcase[0];
expect(testcase['@classname']).toBe('f1/1st API');
});
it('should handle request errors', () => {
const results = [
{

View File

@@ -10,11 +10,7 @@ function normalizeJunitReport(xmlContent: string): string {
// Replace hostnames with fixed value
.replace(/hostname="[^"]*"/g, 'hostname="test-host"')
// Replace execution times with fixed value
.replace(/time="[^"]*"/g, 'time="0.100"')
// Replace file paths with normalized path
.replace(/file="[^"]*[\\/][^"]*"/g, 'file="/mock/path/to/file.bru"')
// Replace test paths with normalized path
.replace(/classname="[^"]*[\\/][^"]*"/g, 'classname="/test/path/collection"');
.replace(/time="[^"]*"/g, 'time="0.100"');
}
test.describe('Collection Run Report Tests', () => {

View File

@@ -1,29 +1,29 @@
<?xml version="1.0"?>
<testsuites>
<testsuite name="Get User Info" file="/mock/path/to/file.bru" errors="0" failures="0" skipped="0" tests="4" timestamp="2024-01-01T00:00:00.000" hostname="test-host" time="0.100">
<testcase name="Status code is 200" status="pass" classname="/test/path/collection" time="0.100"/>
<testcase name="Response is an object" status="pass" classname="/test/path/collection" time="0.100"/>
<testcase name="Response has slideshow property" status="pass" classname="/test/path/collection" time="0.100"/>
<testcase name="Slideshow has title" status="pass" classname="/test/path/collection" time="0.100"/>
<testsuite name="Get User Info" file="api/v1/users.bru" errors="0" failures="0" skipped="0" tests="4" timestamp="2024-01-01T00:00:00.000" hostname="test-host" time="0.100">
<testcase name="Status code is 200" status="pass" classname="api/v1/users" time="0.100"/>
<testcase name="Response is an object" status="pass" classname="api/v1/users" time="0.100"/>
<testcase name="Response has slideshow property" status="pass" classname="api/v1/users" time="0.100"/>
<testcase name="Slideshow has title" status="pass" classname="api/v1/users" time="0.100"/>
</testsuite>
<testsuite name="Get UUID" file="/mock/path/to/file.bru" errors="0" failures="1" skipped="0" tests="5" timestamp="2024-01-01T00:00:00.000" hostname="test-host" time="0.100">
<testcase name="This test will fail" status="fail" classname="/test/path/collection" time="0.100">
<testsuite name="Get UUID" file="api/v1/posts.bru" errors="0" failures="1" skipped="0" tests="5" timestamp="2024-01-01T00:00:00.000" hostname="test-host" time="0.100">
<testcase name="This test will fail" status="fail" classname="api/v1/posts" time="0.100">
<failure type="failure" message="expected 200 to equal 404"/>
</testcase>
<testcase name="Status code is 200" status="pass" classname="/test/path/collection" time="0.100"/>
<testcase name="Response is an object" status="pass" classname="/test/path/collection" time="0.100"/>
<testcase name="Response has uuid property" status="pass" classname="/test/path/collection" time="0.100"/>
<testcase name="UUID is a string" status="pass" classname="/test/path/collection" time="0.100"/>
<testcase name="Status code is 200" status="pass" classname="api/v1/posts" time="0.100"/>
<testcase name="Response is an object" status="pass" classname="api/v1/posts" time="0.100"/>
<testcase name="Response has uuid property" status="pass" classname="api/v1/posts" time="0.100"/>
<testcase name="UUID is a string" status="pass" classname="api/v1/posts" time="0.100"/>
</testsuite>
<testsuite name="Login Request" file="/mock/path/to/file.bru" errors="0" failures="0" skipped="0" tests="3" timestamp="2024-01-01T00:00:00.000" hostname="test-host" time="0.100">
<testcase name="Status code is 200" status="pass" classname="/test/path/collection" time="0.100"/>
<testcase name="Response has json field" status="pass" classname="/test/path/collection" time="0.100"/>
<testcase name="Response json has username" status="pass" classname="/test/path/collection" time="0.100"/>
<testsuite name="Login Request" file="auth/login.bru" errors="0" failures="0" skipped="0" tests="3" timestamp="2024-01-01T00:00:00.000" hostname="test-host" time="0.100">
<testcase name="Status code is 200" status="pass" classname="auth/login" time="0.100"/>
<testcase name="Response has json field" status="pass" classname="auth/login" time="0.100"/>
<testcase name="Response json has username" status="pass" classname="auth/login" time="0.100"/>
</testsuite>
<testsuite name="Logout Request" file="/mock/path/to/file.bru" errors="0" failures="1" skipped="0" tests="2" timestamp="2024-01-01T00:00:00.000" hostname="test-host" time="0.100">
<testcase name="This test will also fail" status="fail" classname="/test/path/collection" time="0.100">
<testsuite name="Logout Request" file="auth/logout.bru" errors="0" failures="1" skipped="0" tests="2" timestamp="2024-01-01T00:00:00.000" hostname="test-host" time="0.100">
<testcase name="This test will also fail" status="fail" classname="auth/logout" time="0.100">
<failure type="failure" message="expected 200 to equal 500"/>
</testcase>
<testcase name="Status code is 200" status="pass" classname="/test/path/collection" time="0.100"/>
<testcase name="Status code is 200" status="pass" classname="auth/logout" time="0.100"/>
</testsuite>
</testsuites>

View File

@@ -1,29 +1,29 @@
<?xml version="1.0"?>
<testsuites>
<testsuite name="Get User Info" file="/mock/path/to/file.bru" errors="0" failures="0" skipped="0" tests="4" timestamp="2024-01-01T00:00:00.000" hostname="test-host" time="0.100">
<testcase name="Status code is 200" status="pass" classname="/test/path/collection" time="0.100"/>
<testcase name="Response is an object" status="pass" classname="/test/path/collection" time="0.100"/>
<testcase name="Response has slideshow property" status="pass" classname="/test/path/collection" time="0.100"/>
<testcase name="Slideshow has title" status="pass" classname="/test/path/collection" time="0.100"/>
<testsuite name="Get User Info" file="api/v1/users.bru" errors="0" failures="0" skipped="0" tests="4" timestamp="2024-01-01T00:00:00.000" hostname="test-host" time="0.100">
<testcase name="Status code is 200" status="pass" classname="api/v1/users" time="0.100"/>
<testcase name="Response is an object" status="pass" classname="api/v1/users" time="0.100"/>
<testcase name="Response has slideshow property" status="pass" classname="api/v1/users" time="0.100"/>
<testcase name="Slideshow has title" status="pass" classname="api/v1/users" time="0.100"/>
</testsuite>
<testsuite name="Get UUID" file="/mock/path/to/file.bru" errors="0" failures="1" skipped="0" tests="5" timestamp="2024-01-01T00:00:00.000" hostname="test-host" time="0.100">
<testcase name="This test will fail" status="fail" classname="/test/path/collection" time="0.100">
<testsuite name="Get UUID" file="api/v1/posts.bru" errors="0" failures="1" skipped="0" tests="5" timestamp="2024-01-01T00:00:00.000" hostname="test-host" time="0.100">
<testcase name="This test will fail" status="fail" classname="api/v1/posts" time="0.100">
<failure type="failure" message="expected 200 to equal 404"/>
</testcase>
<testcase name="Status code is 200" status="pass" classname="/test/path/collection" time="0.100"/>
<testcase name="Response is an object" status="pass" classname="/test/path/collection" time="0.100"/>
<testcase name="Response has uuid property" status="pass" classname="/test/path/collection" time="0.100"/>
<testcase name="UUID is a string" status="pass" classname="/test/path/collection" time="0.100"/>
<testcase name="Status code is 200" status="pass" classname="api/v1/posts" time="0.100"/>
<testcase name="Response is an object" status="pass" classname="api/v1/posts" time="0.100"/>
<testcase name="Response has uuid property" status="pass" classname="api/v1/posts" time="0.100"/>
<testcase name="UUID is a string" status="pass" classname="api/v1/posts" time="0.100"/>
</testsuite>
<testsuite name="Login Request" file="/mock/path/to/file.bru" errors="0" failures="0" skipped="0" tests="3" timestamp="2024-01-01T00:00:00.000" hostname="test-host" time="0.100">
<testcase name="Status code is 200" status="pass" classname="/test/path/collection" time="0.100"/>
<testcase name="Response has json field" status="pass" classname="/test/path/collection" time="0.100"/>
<testcase name="Response json has username" status="pass" classname="/test/path/collection" time="0.100"/>
<testsuite name="Login Request" file="auth/login.bru" errors="0" failures="0" skipped="0" tests="3" timestamp="2024-01-01T00:00:00.000" hostname="test-host" time="0.100">
<testcase name="Status code is 200" status="pass" classname="auth/login" time="0.100"/>
<testcase name="Response has json field" status="pass" classname="auth/login" time="0.100"/>
<testcase name="Response json has username" status="pass" classname="auth/login" time="0.100"/>
</testsuite>
<testsuite name="Logout Request" file="/mock/path/to/file.bru" errors="0" failures="1" skipped="0" tests="2" timestamp="2024-01-01T00:00:00.000" hostname="test-host" time="0.100">
<testcase name="This test will also fail" status="fail" classname="/test/path/collection" time="0.100">
<testsuite name="Logout Request" file="auth/logout.bru" errors="0" failures="1" skipped="0" tests="2" timestamp="2024-01-01T00:00:00.000" hostname="test-host" time="0.100">
<testcase name="This test will also fail" status="fail" classname="auth/logout" time="0.100">
<failure type="failure" message="expected 200 to equal 500"/>
</testcase>
<testcase name="Status code is 200" status="pass" classname="/test/path/collection" time="0.100"/>
<testcase name="Status code is 200" status="pass" classname="auth/logout" time="0.100"/>
</testsuite>
</testsuites>

View File

@@ -1,29 +1,29 @@
<?xml version="1.0"?>
<testsuites>
<testsuite name="Get User Info" file="/mock/path/to/file.bru" errors="0" failures="0" skipped="0" tests="4" timestamp="2024-01-01T00:00:00.000" hostname="test-host" time="0.100">
<testcase name="Status code is 200" status="pass" classname="/test/path/collection" time="0.100"/>
<testcase name="Response is an object" status="pass" classname="/test/path/collection" time="0.100"/>
<testcase name="Response has slideshow property" status="pass" classname="/test/path/collection" time="0.100"/>
<testcase name="Slideshow has title" status="pass" classname="/test/path/collection" time="0.100"/>
<testsuite name="Get User Info" file="api\v1\users.bru" errors="0" failures="0" skipped="0" tests="4" timestamp="2024-01-01T00:00:00.000" hostname="test-host" time="0.100">
<testcase name="Status code is 200" status="pass" classname="api\v1\users" time="0.100"/>
<testcase name="Response is an object" status="pass" classname="api\v1\users" time="0.100"/>
<testcase name="Response has slideshow property" status="pass" classname="api\v1\users" time="0.100"/>
<testcase name="Slideshow has title" status="pass" classname="api\v1\users" time="0.100"/>
</testsuite>
<testsuite name="Get UUID" file="/mock/path/to/file.bru" errors="0" failures="1" skipped="0" tests="5" timestamp="2024-01-01T00:00:00.000" hostname="test-host" time="0.100">
<testcase name="This test will fail" status="fail" classname="/test/path/collection" time="0.100">
<testsuite name="Get UUID" file="api\v1\posts.bru" errors="0" failures="1" skipped="0" tests="5" timestamp="2024-01-01T00:00:00.000" hostname="test-host" time="0.100">
<testcase name="This test will fail" status="fail" classname="api\v1\posts" time="0.100">
<failure type="failure" message="expected 200 to equal 404"/>
</testcase>
<testcase name="Status code is 200" status="pass" classname="/test/path/collection" time="0.100"/>
<testcase name="Response is an object" status="pass" classname="/test/path/collection" time="0.100"/>
<testcase name="Response has uuid property" status="pass" classname="/test/path/collection" time="0.100"/>
<testcase name="UUID is a string" status="pass" classname="/test/path/collection" time="0.100"/>
<testcase name="Status code is 200" status="pass" classname="api\v1\posts" time="0.100"/>
<testcase name="Response is an object" status="pass" classname="api\v1\posts" time="0.100"/>
<testcase name="Response has uuid property" status="pass" classname="api\v1\posts" time="0.100"/>
<testcase name="UUID is a string" status="pass" classname="api\v1\posts" time="0.100"/>
</testsuite>
<testsuite name="Login Request" file="/mock/path/to/file.bru" errors="0" failures="0" skipped="0" tests="3" timestamp="2024-01-01T00:00:00.000" hostname="test-host" time="0.100">
<testcase name="Status code is 200" status="pass" classname="/test/path/collection" time="0.100"/>
<testcase name="Response has json field" status="pass" classname="/test/path/collection" time="0.100"/>
<testcase name="Response json has username" status="pass" classname="/test/path/collection" time="0.100"/>
<testsuite name="Login Request" file="auth\login.bru" errors="0" failures="0" skipped="0" tests="3" timestamp="2024-01-01T00:00:00.000" hostname="test-host" time="0.100">
<testcase name="Status code is 200" status="pass" classname="auth\login" time="0.100"/>
<testcase name="Response has json field" status="pass" classname="auth\login" time="0.100"/>
<testcase name="Response json has username" status="pass" classname="auth\login" time="0.100"/>
</testsuite>
<testsuite name="Logout Request" file="/mock/path/to/file.bru" errors="0" failures="1" skipped="0" tests="2" timestamp="2024-01-01T00:00:00.000" hostname="test-host" time="0.100">
<testcase name="This test will also fail" status="fail" classname="/test/path/collection" time="0.100">
<testsuite name="Logout Request" file="auth\logout.bru" errors="0" failures="1" skipped="0" tests="2" timestamp="2024-01-01T00:00:00.000" hostname="test-host" time="0.100">
<testcase name="This test will also fail" status="fail" classname="auth\logout" time="0.100">
<failure type="failure" message="expected 200 to equal 500"/>
</testcase>
<testcase name="Status code is 200" status="pass" classname="/test/path/collection" time="0.100"/>
<testcase name="Status code is 200" status="pass" classname="auth\logout" time="0.100"/>
</testsuite>
</testsuites>