On this page
A failed automated result is more useful when the screenshot, browser trace, or log is attached to
the same TestCollab execution. Starting with @testcollab/cli 1.17.0,
tc report can read attachment markers from JUnit XML, upload the referenced files,
and link them to the matching test case execution.
This feature applies to JUnit XML only. Mochawesome JSON results can be uploaded, but attachment markers in Mochawesome are not processed. If the XML structure is unfamiliar, see JUnit XML Format Explained.
Attachments fit inside the standard createTestPlan, test runner, and
report path. They do not require createBuild or gate.
Use one attachment marker per line
Put each file path on its own line inside the test case's <system-out> element:
<testcase
classname="Authentication"
name="[TC-42] customer can sign in"
>
<failure message="Expected dashboard URL" />
<system-out><![CDATA[
[[ATTACHMENT|test-results/login/test-failed-1.png]]
[[ATTACHMENT|test-results/login/browser.log]]
[[ATTACHMENT|test-results/login/trace.zip]]
]]></system-out>
</testcase>
The marker is case-insensitive, but it must occupy the complete line. Leading and trailing
whitespace are allowed. A log sentence that only mentions [[ATTACHMENT|file]] in the
middle of a line is ignored.
Some runners add an optional JSON part:
[[ATTACHMENT|test-results/login/browser.log|{"name":"browser console"}]]
The CLI accepts this form but ignores the JSON metadata. The uploaded file uses its filename.
Playwright can emit the markers automatically
Playwright's JUnit reporter writes an attachment marker for each attachment that Playwright recorded for a test. Configure Playwright to retain the evidence and write JUnit XML to a file:
// playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
reporter: [['junit', { outputFile: 'test-results/results.xml' }]],
use: {
screenshot: 'only-on-failure',
video: 'retain-on-failure',
trace: 'retain-on-failure'
}
});
npx playwright test
tc report \
--project 123 \
--test-plan-id 456 \
--format junit \
--result-file ./test-results/results.xml
Keep the JUnit file and Playwright's artifact directory on the same CI agent until
tc report finishes. See
Playwright Test Reports
for a complete setup.
Emit markers from another test runner
For another framework, print the marker while the test runs and configure its JUnit reporter to
retain captured standard output in <system-out>. For example:
# Pytest test code
def attach_to_junit(file_path):
print(f"[[ATTACHMENT|{file_path}]]")
def test_login(page):
# Test steps...
attach_to_junit("test-results/login-failure.png")
// Jest test code
function attachToJunit(filePath) {
console.log(`[[ATTACHMENT|${filePath}]]`);
}
test('[TC-42] customer can sign in', async () => {
// Test steps...
attachToJunit('test-results/login-failure.png');
});
Reporter behavior varies. Some JUnit reporters discard console output unless an option is enabled.
Open the generated XML and verify the marker is inside the correct test case's
<system-out> before relying on it in CI.
How file paths are resolved
An attachment path can be:
- An absolute path to a file on the CI agent
- Relative to the directory where
tc reportruns - Relative to the directory containing the file passed to
--result-file
For a relative path, the CLI checks the current working directory first and the result file's directory second. If the same relative path exists in both places, the current working directory wins. Duplicate paths within one test case are attached once.
The file must still exist locally when the upload runs. Publishing or deleting the runner's
artifact directory before tc report makes the marker unresolvable.
Limits and supported file types
- Up to 10 successfully resolved files per test case
- Up to 10 MB per file, calculated as 10 x 1024 x 1024 bytes
- Markers are deduplicated in document order
The CLI assigns a known content type to these extensions:
Images: .png .jpg .jpeg .gif .webp .svg
Documents: .pdf .txt .log .csv .json .har .xml .html .htm
Archives: .zip
Video: .webm .mp4
An unknown extension is sent as application/octet-stream. The TestCollab server can
still reject a file based on its upload policy.
What happens when an attachment fails
Result status is updated before attachments are processed. A missing, unreadable, oversized,
extra, rejected, or un-linkable attachment produces a warning and is skipped. Attachment-related
warnings do not change the exit status of an otherwise successful tc report command.
This does not mean every tc report error exits 0. Invalid arguments, a missing or
invalid result file, authentication failures, and fatal API errors exit 1. Read the upload summary
and warnings to distinguish a successful result upload with missing evidence from a failed result
upload.
Where attachments appear in TestCollab
Each file is linked to the individual executed test case that contained the marker. It is not added as a test-plan-level or build-level attachment. Open the test plan run, select the executed case, and review its attachments with the result and failure details.
The test itself must map to an execution first. Use a marker such as [TC-42], confirm
the case belongs to the target plan, and make sure the execution is assigned to the user who owns
the API token.
Use the EU region
For an EU-hosted account, add this option to tc report:
--api-url https://api-eu.testcollab.io
Troubleshooting
The marker is ignored
Confirm you uploaded with --format junit, the marker is inside that test case's
<system-out>, and nothing except whitespace shares its line. The syntax is
[[ATTACHMENT|path]] with two closing brackets.
The CLI reports attachment not found
Run tc report from the same workspace as the test runner, or make the path relative
to the JUnit file. Confirm an earlier CI step did not move or remove the artifact.
The file uploads but does not appear on the expected case
Verify the marker is inside the expected <testcase>, not a suite-level
<system-out>. Then check the [TC-42] mapping and the token owner's
assignment.
The pipeline passes after an attachment warning
This is expected. Attachment problems are nonfatal by design. If missing evidence must block your workflow, scan the CLI output for attachment warnings or add a separate file-existence check before reporting. The optional TestCollab quality gate evaluates case statuses, not whether every attachment uploaded.


