将参数传递给 dotnet 测试项目?

问题描述 投票:0回答:3

我在 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

但是他们每次都输出这个消息。请注意

hello
world
都不存在:

[“C:\Users\____\.nuget\packages\microsoft.testplatform.testhost .0.0\lib etstandard1.5 esthost.dll","--端口","55032","--parentprocessid","24440"]

第一个字符串只是正在运行的程序集的名称——第一个命令行参数的相当标准。我不知道

--port
--parentprocessid
的论点来自哪里。

此外,这些变化使

dotnet test
One or more runsettings provided contain invalid token
窒息(原文如此):

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

编辑:看起来

GetCommandLineArgs()
不是一个很好的选择,即使它在这里确实有效。

此外,2006 年 Social.msdn.microsoft.com 上这个问题的答案 说:

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

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

dotnet test

在其他新闻中,SO 上的这个人怀疑命令行参数是否可以传递给 DLL,但是他错了

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

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

c# automated-tests integration-testing .net-core
3个回答
4
投票

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

目前无法向任何.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 TestUser=%1
SET TestPassword=%2
SET TestUrl=%3
DOTNET TEST mytest.csproj

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

#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)

run Azure DevOps command task


1
投票

您可以像这样将 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();

0
投票

我想我的做法都是错误的。结合以下两件事可能是最好的方法。

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

TestMethod
现在是一个 integration 测试,而不是 unit 测试,因为它取决于命令行参数。

如果我重构

TestMethod
,以便它从这样的接口获取命令行参数:

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

...然后这会将

TestMethod
转换为单元测试,其中
IArgumentsProvider
可以被模拟,以便仅测试
TestMethod
中的功能(这就是单元测试的定义)。

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

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.