为vstest.console.exe指定结果文件名

66

可能是一个愚蠢的问题,但有没有人知道如何指定 文件名 作为 VSTEST.Console.exe 运行的输出?我的命令行如下:

 vstest.console.exe [assembly] /logger:trx

运行结束时,控制台会显示以下内容:

 ResultsFile: somepath\TestResults\{username}_{workstation} {timestamp}.trx

我尝试使用.runsettings文件来指定输出位置,但它似乎只控制输出目录,而不是输出文件。我没有找到其他可以控制它的东西。

我想解析TRX文件并生成报告(这已经可以实现了,但如果我不能指定TRX文件的输出路径,我就不知道在脚本中从哪里提取它!)

我一定漏掉了什么......

4个回答

65

编辑:请查看 @AnaFranco 的回答 - 显然自从VS2017以来,可以像这样配置文件名:

vstest.console.exe [assembly] /logger:trx;LogFileName=[filename].trx

为了保存记录和之前的版本,我将保留旧的回答。


不,你没有漏掉什么。TRX日志记录器不支持任何参数(不像TFS发布程序记录器)。

日志记录器程序集位于"C:\ Program Files(x86)\ Microsoft Visual Studio 11.0 \ Common7 \ IDE \ CommonExtensions \ Microsoft \ TestWindow \ Extensions \ Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger.dll"中。如果在您喜欢的.NET反编译器中查看它,您会看到TrxLogger.GetTrxFileName方法。它使用一些关于当前测试运行的基本知识来生成格式为{username}_{workstation} {timestamp}.trx的混淆名称,并且在可感知的方式上不可配置。

据我所知,除非另有配置,否则TRX文件将在当前工作目录下的TestResults\文件夹中创建。你可以:

  • 创建一个新的临时文件夹
  • 将当前目录更改为该文件夹
  • 运行测试运行器
  • 使用您喜欢的递归文件搜索方法扫描结果.trx文件,然后完成操作

至少这是我在我们的构建中(MSBuild,呜呜)做的事情:

<ItemGroup>
  <TestResult Include="**\*.trx"/>
</ItemGroup>

即,在当前目录下收集所有的.trx文件,并将它们放入@(TestResult)项目组中以进行进一步处理。


3
我将此与.runsettings文件一起使用,将trx文件放入已知的临时文件夹中,然后将其复制到我想要的位置并以我想要的名称保存。谢谢。不过,我们可以谈谈微软的半成品程序。 - syazdani
这就是我到目前为止所做的,syazdani。微软不允许你在命令行中指定报告名称,这真的很糟糕。 - Steve Ankeny
1
有一个PowerShell脚本可以提取trx文件。在使用VSTest运行单元测试而不是MSTest中有这个脚本。 - Michael Freidgeim

18

这对我在测试 .NET Core 上起了作用,但我还没有尝试过 .NET Framework。

vstest.console.exe [assembly] /logger:trx;LogFileName=[filename].trx

也许这是一个新事物

更新:使用最新的测试平台和 vstest.console.exe,这也适用于 .net 框架项目。


具体来说,这只在Visual Studio 2017中开始工作。 - Rami A.
1
对于那些在 Visual Studio 之外运行 vstest.console.exe 的用户,此功能从 VSTest 版本 [15.0.0-preview-20161227.02](https://github.com/microsoft/vstest-docs/blob/master/docs/releases.md#1500-preview-2016122702)开始提供。 - jarmanso7

16

显然,你可以指定一个目录来存放*.trx文件(不是文件本身)。然而,这是通过.runsettings文件而不是通过命令行完成的。

引自Bhuvaneshwari的博客

如果需要覆盖结果的默认位置,用户需要使用runsettings文件传递该值。

例如:

Mstest.exe /testcontainer:abc.dll /results:C:\Results.trx 

Vstest.console.exe abc.dll /settings:output.runsettings 

其中.runsettings文件的上下文可能如下所示:

<?xml version="1.0" encoding="UTF-8"?> 
<RunSettings> 
  <RunConfiguration>
   <ResultsDirectory>c:\</ResultsDirectory>
  </RunConfiguration>
 </RunSettings>

11

我也遇到了这个问题。我决定编写一个 MSBuild 目标,通过 EXEC 任务执行 vstest.console ,处理所有输出,包括覆盖率结果。

基本上,我捕获了 vstest 的输出,并使用正则表达式捕获输出中的 *.trx 和 *.coverage 部分,这非常容易。另外,它会删除 TestResults 目录,以保持工作区整洁。

最终,您将获得 *.trx 文件和 *.coverage 文件(可选)。

这个脚本可能看起来有点复杂,但它符合我们的需求。我尝试整理了一下。希望这可以帮到您。

<Target Name="Test" DependsOnTargets="Build">
    <!-- Declare the defaults and arrange parameters -->
    <PropertyGroup>
      <ArtifactsPath Condition=" '$(ArtifactsPath)' == '' ">Artifacts</ArtifactsPath>
      <VSTestSessionName Condition=" '$(VSTestSessionName)' == ''">TestResults</VSTestSessionName>
      <VSTestExe Condition=" '$(VSTestExe)' == '' ">C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe</VSTestExe>
      <VSTestFailBuildOnTestFail Condition=" '$(VSTestFailBuildOnTestFail)' == '' ">false</VSTestFailBuildOnTestFail>
      <VSTestInIsolation Condition=" '$(VSTestInIsolation)' == '' ">true</VSTestInIsolation>
      <VSTestUseVsixExtensions Condition=" '$(VSTestUseVsixExtensions)' == '' ">true</VSTestUseVsixExtensions>
      <VSTestFramework Condition=" '$(VSTestFramework)' == '' ">framework45</VSTestFramework>
      <VSTestLogger Condition=" '$(VSTestLogger)' == '' ">trx</VSTestLogger>
      <ErrorCode>0</ErrorCode>
    </PropertyGroup>
    <ItemGroup>
      <VSTestResultsPath Include="$(VSTestResultsPath)" />
      <VSTestParams Include="@(VSTestFiles ->'&quot;%(FullPath)&quot;', ' ')" />
      <VSTestParams Condition="$(VSTestEnableCodeCoverage)" Include="/EnableCodeCoverage" />
      <VSTestParams Condition="$(VSTestInIsolation)" Include="/InIsolation" />
      <VSTestParams Include="/UseVsixExtensions:$(VSTestUseVsixExtensions)" />
      <VSTestParams Include="/Framework:$(VSTestFramework)" />
      <VSTestParams Include="/Logger:$(VSTestLogger)" />
      <VSTestParams Condition="$(VSTestCaseFilter) != ''" Include="/TestCaseFilter:&quot;$(VSTestCaseFilter)&quot;" />
      <VSTestParams Condition="$(VSTestRunSettings) != ''" Include="/Settings:&quot;$(VSTestRunSettings)&quot;" />
    </ItemGroup>

    <Message Text="TestAssembly: %(VSTestFiles.Identity)" Importance="high"/>

    <Exec ContinueOnError="!$(VSTestFailBuildOnTestFail)" ConsoleToMSBuild="true" WorkingDirectory="$(WorkingDirectory)" Condition=" '@(VSTestFiles)' != ''" 
          Command="&quot;$(VSTestExe)&quot; @(VSTestParams, ' ')">
      <Output TaskParameter="ExitCode" PropertyName="ErrorCode"/>
      <Output TaskParameter="ConsoleOutput" PropertyName="OutputOfExec" />
    </Exec>
    <Message Importance="high" Text="VSTest exitcode: $(ErrorCode)"/>

    <!-- Use the VSTest output to discover the Results & Coverage files respectively -->
    <PropertyGroup>
      <!-- Unencoded Regex: (?<=(Results file: )).*?(?=\;)|(?<=(Attachments:;)).*?(?=\;) -->
      <ResultsFileRegexPattern>(?&lt;=(Results File: )).*.trx</ResultsFileRegexPattern>
      <CoverageFileRegexPattern>(?&lt;=(Attachments:;)).*.coverage</CoverageFileRegexPattern>
      <SourceResultsFile>$([System.Text.RegularExpressions.Regex]::Match($(OutputOfExec), $(ResultsFileRegexPattern)))</SourceResultsFile>
      <SourceCoverageFile Condition="$(VSTestEnableCodeCoverage)">$([System.Text.RegularExpressions.Regex]::Match($(OutputOfExec), $(CoverageFileRegexPattern)))</SourceCoverageFile>
    </PropertyGroup>

    <ItemGroup>
      <TestArtifact Include="$(SourceResultsFile)" />
      <TestArtifact Include="$(SourceCoverageFile)" />
    </ItemGroup>

    <Warning Condition=" '$(SourceResultsFile)' == '' " Text=".trx file not found" />
    <Warning Condition=" $(VSTestEnableCodeCoverage) and '$(SourceCoverageFile)' == '' " Text=".coverage file not found" />

    <!-- Copy files to the artifact directory -->
    <Copy SourceFiles="@(TestArtifact)" DestinationFiles="@(TestArtifact->'$(ArtifactsPath)\$(VSTestSessionName)%(Extension)')" />

    <!-- Clear the test results temporary directory -->
    <RemoveDir Directories="@(TestResults)" />

    <ItemGroup>
      <TestFile Include="$(ArtifactsPath)\**\$(VSTestSessionName).trx" />
      <CoverageFile Include="$(ArtifactsPath)\**\$(VSTestSessionName).coverage" />
    </ItemGroup>

    <Message Text="TestReport: @(TestFile)" />
    <Message Text="CoverageReport: @(CoverageFile)" />
</Target>

2
为了避免硬编码 Visual Studio 的路径,您可以执行以下操作。 <VisualStudioFolder>$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\12.0@ShellFolder)</VisualStudioFolder> <VsTestFolder>$([System.IO.Path]::Combine("$(VisualStudioFolder)", "Common7", "IDE", "CommonExtensions", "Microsoft", "TestWindow"))\</VsTestFolder> <VSTestExe>$(VsTestFolder)vstest.console.exe</VSTestExe> - TealFawn
我必须使用 HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\12.0_Config - smg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接