Skip to main content

xUnit and .runsettings: An Amazing Duo for Test Data

·546 words·3 mins

At the start of 2026, my manager made it a goal for our team to gather more data for our test runs. The only way I could before this was with my HTML reports, but there was no way to digest this data to show it in charts. So, I started to plan out how I could get metrics on all of our test runs so we could report the total number of tests ran, failures/passes and how long they took (aka, how much manual testing time we’ve saved).

To start, I looked at my xUnit runner json that I had already. I was thinking that there may be something there I could use to help me get more numbers. That… was not the case. The xUnit runner was really only used to help make sure tests ran the way you want them to. Here’s an example of this json file that one could make to for xUnit:


{
  "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json",
  "parallelizeAssembly": true,
  "parallelizeTestCollections": true,
  "maxParallelThreads": 5
}

That specific example allows up to 5 classes to run at any given time at the same time.

So, I did more digging. I knew that dotnet test generated a file called a .trx, when you run it on an Azure CI/CD pipeline. Focusing on that, I found you can make a .runsettings file that dotnet test can use to generate trx files in a specific folder (if set properly). Below is an example of a .runsettings:


<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
  <!-- Configurations that affect the Test Framework -->
  <RunConfiguration>
    <MaxCpuCount>1</MaxCpuCount>
    <ResultsDirectory>.\TestResults</ResultsDirectory>

  </RunConfiguration>

   <LoggerRunSettings>
    <Loggers>
      <Logger friendlyName="trx" enabled="True">
        <Configuration>
          <LogFileName>foo.trx</LogFileName>
        </Configuration>
      </Logger>
      <Logger friendlyName="blame" enabled="True" />
    </Loggers>
  </LoggerRunSettings>

</RunSettings>

This file would generate trx files in a TestResults folder.

I also learned that you can have the two merged apparently, but it failed to work for me. Let’s take the two examples I’ve made to make one .runsettings anyway:


<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
  <!-- Configurations that affect the Test Framework -->
  <RunConfiguration>
    <MaxCpuCount>1</MaxCpuCount>
    <ResultsDirectory>.\TestResults</ResultsDirectory>

  </RunConfiguration>

  <xUnit>
    <MaxParallelThreads>5</MaxParallelThreads>
    <ParallelizeTestCollections>true</ParallelizeTestCollections>
    <DiagnosticMessages>true</DiagnosticMessages>
  </xUnit>

   <LoggerRunSettings>
    <Loggers>
      <Logger friendlyName="trx" enabled="True">
        <Configuration>
          <LogFileName>foo.trx</LogFileName>
        </Configuration>
      </Logger>
      <Logger friendlyName="blame" enabled="True" />
    </Loggers>
  </LoggerRunSettings>

</RunSettings>

I settled on just having the two files, and this has worked for a few months now. I took an example trx file and fed it to a AI tool to help me generate a console tool to help me auto populate a CSV file that reads the file and sorts the results by project and by date. At some point, I want to remake this tool and post it to my GitHub. Check back and maybe I’ll have a link to it!

Since implementing all of this, our leadership has loved seeing the numbers. The fact that on average, I spent around 50-250 hours running automation (I often run automation overnight when I work from home), and that my automation has saved us so much manual time has been a big plus. It’s also shown how much effort goes into my work every sprint. I’m hoping to keep improving this tool, I have so many idea. Mainly, I want to see if I can make a docker container that can make pretty charts using all that data. If you know of one that can read trx files, shoot me an email!