You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过C#代码直接生成.trx单元测试结果文件?

直接用C#代码生成VSTest .trx测试结果文件

绝对可以!你不需要通过启动cmd.exe的间接方式,直接用C#调用Visual Studio测试平台的官方API就能生成.trx测试结果文件,这样不仅更高效,还能获得更好的可控性。

先看一下你当前通过cmd调用的实现:

System.Diagnostics.Process process = new System.Diagnostics.Process(); 
System.Diagnostics.ProcessStartInfo myStartInfo = new System.Diagnostics.ProcessStartInfo(); 
myStartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; 
myStartInfo.UseShellExecute = false; 
myStartInfo.FileName = "cmd.exe"; 
myStartInfo.Verb = "runas"; 
myStartInfo.WorkingDirectory = @"C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\CommonExtensions\Microsoft\TestWindow"; 
myStartInfo.Arguments = @"/C VSTest.console C:\UnitTestProject1\UnitTestProject1\bin\Debug\UnitTestProject1.dll /logger:trx"; 
process.StartInfo = myStartInfo; 
process.Start();

下面提供两种更优的实现方式:

方法1:使用Microsoft.TestPlatform官方API(推荐)

这是最原生的方式,不需要依赖外部进程,直接在代码中控制测试执行和结果输出。

步骤1:安装NuGet包

首先需要安装两个核心NuGet包:

  • Microsoft.TestPlatform.ObjectModel
  • Microsoft.TestPlatform.TestHost

步骤2:实现代码

using Microsoft.VisualStudio.TestPlatform.ObjectModel;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;

class VSTestRunner
{
    static void Main(string[] args)
    {
        // 检查是否以管理员身份运行,若没有则重启进程获取权限
        if (!IsRunningAsAdministrator())
        {
            RestartProcessAsAdmin();
            return;
        }

        // 配置测试路径和结果文件路径
        string testDllPath = @"C:\UnitTestProject1\UnitTestProject1\bin\Debug\UnitTestProject1.dll";
        string trxOutputPath = Path.Combine(Environment.CurrentDirectory, "TestResults.trx");

        // 初始化测试运行配置
        var runSettings = new RunSettings();
        
        // 配置TRX日志记录器,指定输出文件
        var loggerConfig = new Dictionary<string, string>
        {
            { "LogFileName", trxOutputPath }
        };
        runSettings.AddLogger("trx", loggerConfig);

        // 创建测试请求
        var testRequest = new TestRunRequest(testDllPath);
        testRequest.RunSettings = runSettings;

        // 创建测试客户端并监听日志
        using var testClient = new TestPlatformClient();
        testClient.TestRunMessage += (sender, eventArgs) =>
        {
            if (eventArgs.MessageLevel == TestMessageLevel.Error)
            {
                Console.WriteLine($"测试错误: {eventArgs.Message}");
            }
            else if (eventArgs.MessageLevel == TestMessageLevel.Informational)
            {
                Console.WriteLine($"测试信息: {eventArgs.Message}");
            }
        };

        // 执行测试并等待完成
        TestRunResult result = testClient.RunTests(testRequest);
        Console.WriteLine($"\n测试执行完成!结果已保存到: {trxOutputPath}");
        Console.WriteLine($"总测试数: {result.TestsTotal}, 通过: {result.TestsPassed}, 失败: {result.TestsFailed}");
    }

    // 检查当前进程是否以管理员身份运行
    private static bool IsRunningAsAdministrator()
    {
        using var identity = System.Security.Principal.WindowsIdentity.GetCurrent();
        var principal = new System.Security.Principal.WindowsPrincipal(identity);
        return principal.IsInRole(System.Security.Principal.WindowsBuiltInRole.Administrator);
    }

    // 以管理员身份重启当前进程
    private static void RestartProcessAsAdmin()
    {
        var startInfo = new ProcessStartInfo(Environment.ProcessPath)
        {
            Verb = "runas",
            Arguments = string.Join(" ", Environment.GetCommandLineArgs().Skip(1))
        };

        try
        {
            Process.Start(startInfo);
            Environment.Exit(0);
        }
        catch (System.ComponentModel.Win32Exception)
        {
            Console.WriteLine("用户拒绝了管理员权限请求,无法继续执行测试。");
            Environment.Exit(1);
        }
    }
}

方法2:直接调用VSTest.console.exe(无需NuGet包)

如果你不想引入额外依赖,可以直接调用VSTest.console.exe进程,跳过cmd.exe的中转,同样支持管理员权限:

using System.Diagnostics;

class VSTestProcessRunner
{
    static void Main(string[] args)
    {
        string vstestExePath = @"C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe";
        string testDllPath = @"C:\UnitTestProject1\UnitTestProject1\bin\Debug\UnitTestProject1.dll";

        var startInfo = new ProcessStartInfo(vstestExePath)
        {
            WindowStyle = ProcessWindowStyle.Hidden,
            UseShellExecute = true, // 必须设为true才能使用Verb="runas"请求管理员权限
            Verb = "runas",
            Arguments = $@"""{testDllPath}"" /logger:trx"
        };

        try
        {
            using var process = Process.Start(startInfo);
            process.WaitForExit();
            
            if (process.ExitCode == 0)
            {
                Console.WriteLine("测试执行成功,.trx文件已生成在默认的TestResults目录下");
            }
            else
            {
                Console.WriteLine($"测试执行失败,退出代码: {process.ExitCode}");
            }
        }
        catch (System.ComponentModel.Win32Exception)
        {
            Console.WriteLine("用户拒绝管理员权限,测试无法执行。");
        }
    }
}

注意:此方法中UseShellExecute必须设为true,否则无法通过Verb="runas"获取管理员权限,这和你原来调用cmd.exe的配置不同。

两种方法对比

方法优势劣势
官方API实时监听测试进度、灵活配置测试参数、无外部进程依赖需要引入NuGet包,代码复杂度稍高
直接调用进程无需额外依赖、代码简洁无法实时获取测试细节,只能等待进程结束

内容的提问来源于stack exchange,提问作者Ishan Verma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:00:05