63

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

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

在运行结束时,控制台中出现以下内容:

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

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

我想解析 TRX 文件并从中生成报告(这已经可以了,但是如果我无法指定 TRX 文件的输出路径,我将不知道从脚本中的何处获取它!)

我必须在这里遗漏一些东西......

4

4 回答 4

62

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

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

我将把旧答案留给后代和 2017 年之前的版本。


不,你没有错过任何东西。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,sob):

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

.trx把当前目录下的所有文件都收集起来,塞进@(TestResult)item group做进一步处理。

于 2013-01-24T08:12:30.053 回答
18

这对我测试 .net 核心很有用,我没有用 .net 框架尝试过:

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

也许它是一个新事物

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

于 2017-10-11T01:04:29.000 回答
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>
于 2014-11-05T12:49:56.127 回答
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>
于 2014-02-13T00:56:33.873 回答