【问题标题】:Passing arguments to dotnet test project?将参数传递给 dotnet 测试项目?
【发布时间】:2017-03-24 05:38:00
【问题描述】:

我在 Visual Studio 2017 的 .NET Core 1.1 单元测试项目(不是 xUnit 测试项目)中有以下测试类。如何将命令行参数传递给 TestMethod

[TestClass]
public class TestClass
{
    [TestMethod]
    public void TestMethod()
    {
        var args = Environment.GetCommandLineArgs();
        var json = JsonConvert.SerializeObject(args);
        throw new Exception(json);
    }
}

互联网上的很多地方听起来好像您可以在要传递的参数前面加上 --,但我无法让它工作。

这些是我尝试过的命令:

  • dotnet test TestProject.csproj -- hello=world
  • dotnet test TestProject.csproj -- --hello world
  • dotnet test TestProject.csproj -- -hello world

但是他们每次都输出这个消息。注意helloworld 都不存在:

["C:\Users\____\.nuget\packages\microsoft.testplatform.testhost\15.0.0\lib\netstandard1.5\testhost.dll","--port","55032","- -parentprocessid","24440"]

第一个字符串只是正在运行的程序集的名称——pretty standard for the first command line argument。我不知道--port--parentprocessid 参数来自哪里。

此外,这些变化使dotnet testOne or more runsettings provided contain invalid token 窒息(原文如此):

  • dotnet test TestProject.csproj -- -hello=world
  • dotnet test TestProject.csproj -- --hello=world

编辑:它看起来像 GetCommandLineArgs() isn't that great of an option,即使它确实在这里工作。

另外,the answer to this question on social.msdn.microsoft.com from 2006 说:

实例化这些类以便 VS 对它们进行单元测试的方式与正常执行完全不同。可执行文件无法正常运行,您和 VS 都无法为其提供参数。通过将二进制文件用作类库,这些类的实例化与程序执行无关。 (原文如此)

我想知道这是否仍然适用于dotnet test

在其他新闻中,this guy on SO 怀疑命令行参数是否可以传递给 DLL,但he's wrong

[ 函数的原型:] void CALLBACK EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);

[Rundll] 调用 函数,传递命令行 tail,即

【问题讨论】:

  • 暗示它闻起来像dotnet test 不适合运行集成测试,当您需要将机密/凭据保留在代码之外时,这是我试图让它做的事情

标签: c# automated-tests integration-testing .net-core


【解决方案1】:

这是我在寻找这个答案时遇到的地方之一,所以我在这里分享我的解决方法是公平的。

目前,无法将参数传递给任何 .net 测试项目。您可以使用 mstest testsettings/runsettings 文件,但这需要创建单独的文件。就我而言,我需要一个服务器名和密码来进行 Selenium 编码 UI 测试,但我不想存储它们。

传递参数的推荐方法之一是通过环境变量。因此,在您的 C# xunit 文件中,您可以执行以下操作:

// in mytest.cs
var user = Environment.GetEnvironmentVariable("TestUser");
var password = Environment.GetEnvironmentVariable("TestPassword");
var url = Environment.GetEnvironmentVariable("TestUrl");

如果您不想明确设置环境变量,请记住,您始终可以为会话进程临时设置它们。一种方法是创建一个简单的 cmd 文件

#launchtests.cmd
SETLOCAL
SET TestUser='pete001'
SET TestPassword='secret'
SET TestUrl='http://testserver.local/login'
DOTNET TEST mytest.csproj

现在是有趣的部分。您可以参数化这方面的各个方面。所以你可以把它改成:

#run wity launchtests.cmd pete001 secret 'http://testserver.local/login'
SETLOCAL
SET %1
SET %2
SET %3
DOTNET TEST mytest.csproj

或者,如果您想从 Azure DevOps(fka VSTS 或 TFS)管道启动测试,您可以简单地使用 $(...) 表示法来内联变量,即使它们被标记为秘密和/或来了来自 Azure KeyVault。

#In AzureDevops, variables not marked as secret are already added to the environment
SET TestPassword=$(TestPassword)
dotnet test $(Build.SourcesDirectory)\MyCompany.MyProduct.UITests\MyTest.csproj --configuration $(BuildConfiguration) --collect "Code Coverage" --logger trx --results-directory $(Agent.TempDirectory)

【讨论】:

    【解决方案2】:

    您可以像这样将 Runsettings 传递给测试运行器(例如 bash):

    dotnet test PathToYourTestProject.dll -- 'TestRunParameters.Parameter(name="YourTestProject.Args",value="ServiceConfig:BaseAddress=http://localhost:8080 ServiceConfig:MaxMemory=2048")'
    

    对于其他 shell 类型,这显然是一个正确转义的问题,正如您将看到的那样,这可能会很痛苦。对于 MSTest,可以通过

    访问参数
    var args = TestContext.Properties["YourTestProject.Args"].Split();
    

    【讨论】:

      【解决方案3】:

      我想我做错了。混合以下两件事可能是最好的方法。

      选项 1:从集成测试重构为单元测试

      TestMethod 现在是 integration 测试,而不是 unit 测试,因为它依赖于命令行参数。

      如果我重构 TestMethod 以便它从这样的接口获取命令行参数:

      interface IArgumentsProvider
      {
          IEnumerable<string> GetArguments();
      }
      

      ...然后这会将TestMethod 转换为一个单元测试,其中IArgumentsProvider 可以被模拟,因此只测试TestMethod 中的功能(这是单元测试的定义)。

      请注意,我可能希望将该接口的非模拟实现上的测试移至其他集成测试所在的位置。见下文。

      选项 2:将集成测试从单元测试项目移到部署管道中的其他位置

      并非总是可以将测试重构为单元测试。例如,在某些时候,您会想要保证 Location 控制器在将代码发布到野外之前实际上可以从 SQL 数据库中发布和检索地理坐标。

      这是一个集成测试的例子。集成测试属于部署管道中的其他位置:不要让测试作为单元测试项目中构建定义的一部分执行,而是将其移动到发布定义中并从更合适的框架中调用它。

      【讨论】:

      • 我的解决方案中有单元测试和集成测试。一个项目用于单元,另一个用于集成。如何将变量传递给我的集成测试项目?我需要将仅在 CICD 期间构建时知道的变量传递给测试,以便它知道如何/在何处进行测试。
      • @JerrodHorton 假设你的意思是你有两个dotnet test 项目,我发现dotnet test 是错误的集成测试框架。相反,您可能会考虑创建一个单独的控制台应用程序,您可以构建该应用程序并将这些构建时变量传递给该应用程序。或者,我敢肯定,除了 dotnet test 之外,还有其他出色的框架专门用于集成测试。
      • 无论.net 项目是否适合使用,这是您的看法,但事实仍然是许多人使用它们来执行集成测试。问题依然存在,如何通过命令行将数据传递到 dotnet 测试项目中?
      • @JerrodHorton 我不想听起来像在争论,但是没有办法通过命令行将数据传递到dotnet test 项目中。因此,它不适合那些需要命令行参数的集成测试。因此,必须得出结论,dotnet test 不适合集成测试,因为不可能实现这一大类集成测试。在我看来,更有成效的问题是:除了dotnet test 之外,还有哪些工具可用于实施集成测试?
      • @JerrodHorton 要进一步阅读,我推荐this page from Microsoft。在那里,他们讨论了他们发现对集成测试有用的工具和技术。我并没有具体说你,但是很多人(包括我自己最长时间)不知道 unit 测试和 integration 测试之间的区别。所以当dotnet test's documentation 说它“用于执行单元测试”时,他们并没有抓住其中的微妙之处。
      猜你喜欢
      • 2021-05-25
      • 2015-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-15
      • 2018-12-29
      • 1970-01-01
      相关资源
      最近更新 更多