TRX

A .trx file is Visual Studio's test results format: one XML document per test run, written by dotnet test --logger trx, vstest.console and Azure DevOps test tasks. It is the .NET counterpart to JUnit XML — complete and machine-readable, and unreadable to anyone who opens it in a browser or text editor.

What is inside

<TestRun id="…" name="runner@build-agent 2026-11-08 09:14:02"
         xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
  <Times start="2026-11-08T09:14:02.3Z" finish="2026-11-08T09:14:06.9Z" />
  <Results>
    <UnitTestResult testId="t2" testName="Shop.Tests.CartTests.ApplyCoupon(code: &quot;SAVE10&quot;)"
                    outcome="Failed" duration="00:00:00.3410000">
      <Output>
        <StdOut>Applying coupon SAVE10 to subtotal 90.00</StdOut>
        <ErrorInfo>
          <Message>Assert.Equal() Failure: Values differ …</Message>
          <StackTrace>   at Shop.Tests.CartTests.ApplyCoupon(String code) in CartTests.cs:line 42</StackTrace>
        </ErrorInfo>
      </Output>
    </UnitTestResult>
  </Results>
  <TestDefinitions>
    <UnitTest id="t2" name="ApplyCoupon">
      <TestMethod className="Shop.Tests.CartTests" name="ApplyCoupon" codeBase="Shop.Tests.dll" />
    </UnitTest>
  </TestDefinitions>
  <ResultSummary outcome="Failed">
    <Counters total="5" executed="4" passed="2" failed="2" notExecuted="1" />
  </ResultSummary>
</TestRun>
Element Holds
<Times> When the run was created, started and finished
<Results> One <UnitTestResult> per test executed
<TestDefinitions> One <UnitTest> per test, with its class and assembly
<ErrorInfo> <Message> and <StackTrace> of a failure
<StdOut> / <StdErr> What the test printed (ITestOutputHelper, Console)
<ResultSummary> The run's outcome, <Counters>, and run-level <RunInfos>
<TestLists> / <TestEntries> Bookkeeping that links results to definitions

The result and its class live in different places: a <UnitTestResult testId="t2"> gets its class from the <UnitTest id="t2"> under <TestDefinitions>. className can carry an assembly suffix (Shop.Tests.CartTests, Shop.Tests, Version=1.0.0.0).

The outcome values

outcome Read it as
Passed Pass
Failed An assertion failed or the test threw
Error, Timeout, Aborted The test could not finish
NotExecuted Skipped — [Ignore], xUnit Skip, filtered out
Inconclusive Assert.Inconclusive — neither pass nor fail
PassedButRunAborted, Warning Passed, with something wrong around it

duration is a .NET TimeSpan string — hh:mm:ss.fffffff, with a d. prefix past a day — not seconds.

The parts that bite

  • A run can fail with no failing test. When the test host crashes (a StackOverflowException, an out-of-memory kill, a native crash), the adapter is missing, or a data collector errors, ResultSummary says Failed and the reason is only in <RunInfos><RunInfo><Text>. Tools that list failing tests show a red build and nothing to fix.
  • One file per test project. dotnet test on a solution writes a .trx per project, and without LogFileName each name includes the user, machine and timestamp — so a glob in the CI step has to collect them all.
  • Data-driven tests nest. MSTest [DataRow] results come as a parent <UnitTestResult> with <InnerResults> holding one row each. Count the rows or the parent, never both.
  • testName is sometimes fully qualified. xUnit writes Namespace.Class.Method(arg: 1), MSTest writes Method. Strip the class prefix before displaying it next to the class.
  • No flaky marker. TRX has no retry concept. A rerun (dotnet test --retry-failed-tests in newer Microsoft.Testing.Platform, or a pipeline retry) is a second file, so a flaky test only shows up by comparing runs.
  • The file holds output and paths. Captured StdOut, machine names, user names and source paths are all in it — check before attaching it to a public issue.

Opening one

Visual Studio (Test Explorer → Open) and Rider read .trx natively; community converters (trx2html, trxer) turn it into HTML; Azure DevOps reads it through the Publish Test Results task. For a JUnit file instead, add the JunitXml.TestLogger package and --logger junit next to the trx logger.

Or skip all of that: the free test report viewer reads .trx as-is in the browser. Test classes become suites, the outcome sets the status, the failure message and stack trace come from ErrorInfo, StdOut is kept under the failure, data-driven rows are listed one by one, and a run that failed with no failing test gets its own entry with the RunInfo text. Copy the Markdown summary into the pull request, or publish the report as a link people can comment on.

Try it

Comma is free — unlimited reports, unlimited commenters, unlimited revision history.

Open the TRX viewer →

Related