Exporting test evidence from Azure Test Plans
Screenshots, attachments and step-level notes live in four different places in Azure DevOps, the built-in export carries none of them, and one common way of capturing evidence never reaches a test result at all. Here's the map, the REST endpoints, and the traps.
When an auditor asks you to prove a control was tested, they are not asking for a pass rate. They are asking for the artefact — the screenshot showing the rejected transaction, the note describing what the tester actually saw, and something linking that artefact to a specific execution on a specific date by a specific person.
Azure Test Plans stores all of that. Getting it out is where it gets interesting.
Evidence lives at four different levels
This is the single most useful thing to understand, because "the screenshot is attached to the test" is four different statements in Azure DevOps and they behave differently.
| Level | What lands there | How it gets there |
|---|---|---|
| Test run | Run-scoped files — an environment note, a log covering the whole session | Manually, via + Add attachments in the run details |
| Test result | Per-execution evidence: image action logs, screen recordings, tester-added files | Automatically by the Test Runner's diagnostic capture, or manually |
| Test step | Step-level attachments and the factual Actual Result text | Only via the Actual Result field, which is off by default |
| Sub-result | Data-driven and automated test sub-results | Published by pipelines |
Microsoft is explicit that the first two are separate stores: "Run-level attachments are separate from test result attachments. To view result-specific files, open the result details and select the Attachments tab." If you pull run attachments and assume you have the evidence, you have the environment notes and none of the screenshots.
A small but genuinely annoying limitation: in the Azure DevOps UI you can only preview .txt and .log files. Everything else — including every screenshot — must be downloaded one at a time to be looked at.
Microsoft does not publish a file-size limit for test attachments anywhere in the Test Plans documentation. You will find a 60 MB figure quoted online — that is the work item attachment limit, a different subsystem, and it does not govern test results. If a size limit matters to your process, test it in your own organisation rather than trusting a number from a forum.
The trap: exploratory evidence never reaches a test result
This one is worth an internal memo, because it quietly invalidates a lot of evidence packs.
The Test & Feedback extension has two modes, and they file evidence to completely different places.
When a tester runs an exploratory session, there is no test point being executed, so there is no test result to attach to. The captures — screenshots, notes, screen recordings — go onto the bug or task work item the tester creates, plus the exploratory session record. Microsoft: "The extension creates a work item that contains your feedback and attachments."
When a tester runs a test point from a test plan in the Test Runner, captures attach to the test result. If they then file a bug, everything captured up to that point is copied into the bug as well.
The consequence: evidence gathered exploratively is invisible to any reporting built on test results. Your coverage report, your evidence pack, your traceability matrix — all of them are built from test results, and none of them will ever see the screenshot your best tester captured during an exploratory session. It exists, it's real, it's on a bug somewhere, and your report says the control has no evidence.
If your organisation does a lot of exploratory testing and also has an audit obligation, this gap is probably already costing you.
What the built-in export does not do
Short version: it does not export evidence, and Microsoft says so directly.
The Export option on a test plan or suite produces an email or a print-to-PDF of plan and suite properties and details. Documented limits are 75 test suites per operation and 1 MB of data. And then, verbatim from the Azure Test Plans FAQ:
"You can't export test plan attachments."
The other export people try — Export test cases to CSV/XLSX — exports test cases, not results. ID, title, steps, area path, state, assigned-to. No outcome, no run date, no tester, no attachments. There is no built-in export of test results from Azure Test Plans in any format.
So every evidence pack produced from stock Azure DevOps is assembled by hand, or by a script somebody wrote.
The Actual Result field — new, and worth turning on
This is the most significant thing to happen to manual test evidence in Azure DevOps in years, it went generally available in July 2026, and a surprising number of teams don't know it exists. It answers one of the longest-standing requests on Developer Community.
With it enabled, each test step gains an Actual Result field after the tester marks the step Pass or Fail. They type what actually happened, and they can add step-level attachments. Microsoft's framing is explicitly about audit: it "captures the factual outcome of each step alongside Pass/Fail, giving you structured evidence of what happened during the run."
It distinguishes three things that used to get muddled:
- Expected Result — defined when the test case is authored.
- Actual Result — recorded during execution. Factual. Can serve as audit evidence.
- Comment — informal notes, not structured or enforced.
It is configured per test plan, not globally: Test Plans → your plan → More actions → Test plan settings → Test result settings → Use "Actual Result" field. Three modes:
| Mode | Behaviour |
|---|---|
| Disabled (default) | The field isn't present during execution |
| Enabled – Optional | The field appears; testers may leave it blank |
| Enabled – Required | Testers must fill it in for any step that has a defined Expected Result |
Note the qualifier on Required mode: steps without a defined Expected Result don't require input, even in required mode. If your test cases have sparse expected results, "Required" is quieter than it sounds.
Turning the setting off hides evidence that already exists. Microsoft: "If the setting is disabled, results don't show on the result page, even if they were entered during execution." The data is still there and still retrievable over REST — but it vanishes from the UI, which is where your auditor is looking.
And anyone can turn it off. "Any user with an Azure Test Plans licence can change the Actual Result setting at any time for any test plan they can access." There is no separate permission guarding it beyond Manage test plans on the area path.
One more operational detail: if you change the setting while runs are in progress or paused, the logic that applied when the run started continues to apply for that run — but resuming a paused run picks up the new logic. Microsoft's own advice is to check for in-progress runs before changing it.
Actual Result is Azure DevOps Services only. It is not in Azure DevOps Server.
Getting evidence out over REST
Everything is reachable. All of these are api-version=7.1, in the test area, and need a personal access token with the vso.test scope.
Run-level attachments
GET https://dev.azure.com/{org}/{project}/_apis/test/Runs/{runId}/attachments?api-version=7.1
GET https://dev.azure.com/{org}/{project}/_apis/test/Runs/{runId}/attachments/{attachmentId}?api-version=7.1
Result-level attachments — this is where the screenshots are
GET https://dev.azure.com/{org}/{project}/_apis/test/Runs/{runId}/Results/{resultId}/attachments?api-version=7.1
GET https://dev.azure.com/{org}/{project}/_apis/test/Runs/{runId}/Results/{resultId}/attachments/{attachmentId}?api-version=7.1
Per-step data — iterations carry the step-by-step action results, including Actual Result
GET https://dev.azure.com/{org}/{project}/_apis/test/Runs/{runId}/results/{resultId}
?detailsToInclude=iterations&api-version=7.1
The detailsToInclude parameter defaults to none, which returns only core fields — outcome, state, priority, comments, error message. If you call the results endpoint and wonder where the steps went, this is why. The other values are iterations, workItems, subResults and point.
The download operations are called Get Test Run Attachment Zip and Get Test Result Attachment Zip, but the /attachments/{attachmentId} path returns application/octet-stream or application/zip depending on the file. They are not necessarily zipped. Don't write an unzip step you don't need.
A practical order of work
If you're building an evidence pack, this is the sequence that avoids the most rework:
- Turn on Actual Result for the plan, in Required mode if your test cases have decent expected results. Do this before the cycle starts — it cannot be applied retrospectively.
- Decide your exploratory policy. Either accept that exploratory evidence lives on bugs and report it separately, or require that anything audit-relevant is executed as a test point.
- Pull results with
detailsToInclude=iterationsso you get step-level data in the same call. - Fetch result attachments per result, not run attachments. Run attachments are a different, usually emptier, store.
- Embed, don't link. A report that links back to
dev.azure.comis useless to a reader without a licence — which, as covered in our guide on licence-free reading, is most of your audience. - Record the retrieval date on the artefact. Test results are subject to retention policy, and what you can fetch today may not be fetchable next year.
The retention landmine
Worth ending on, because it surprises people during an audit rather than before one.
Manual test results are governed by a retention setting at Project settings → Test → Retention. When retention deletes test runs and results, Microsoft documents the side effect: the related test points' outcome is set back to Active, and "progress reports may reflect decreased run rates."
Read that again, because it means your historical pass rate can move on its own. A cycle you signed off at 94% can, months later, report a lower run rate — not because anything changed, but because retention ran and the underlying results were deleted.
If you have an evidence obligation that outlives your retention window, exporting evidence isn't a convenience. It is the only copy that will still exist.
Evidence that travels with the report
Testmarshal pulls result-level attachments and step data and embeds them directly in a self-contained report file — one document, evidence inside it, readable without an Azure DevOps licence and still readable after retention has done its work. In development; early access is open.
No spam, and you can leave whenever you like.
Sources
- Record Actual Result for manual tests — Microsoft Learn
- Public Preview: Actual Result for Manual Tests — Azure DevOps Blog, April 2026
- Azure Test Plans Sprint 276 release notes (Actual Result GA) — Microsoft Learn
- Test runs and attachments — Microsoft Learn
- Collect diagnostic data during tests — Microsoft Learn
- Test Attachments REST API reference — Microsoft Learn
- Set test results retention policies — Microsoft Learn
- Azure Test Plans FAQ — Microsoft Learn