繁体   English   中英

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

[英]Passing arguments to dotnet test project?

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

第一个字符串只是正在运行的程序集的名称—— 第一个命令行参数非常标准 我不知道--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,但他错了

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

[Rundll] 调用<entrypoint> 函数,传递命令行尾部,即<可选参数>。

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

目前,没有办法将参数传递给任何 .net 测试项目。 您可以使用 mstest testsettings/runsettings 文件,但这需要创建单独的文件。 就我而言,我的 Selenium Coded 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)

运行 Azure DevOps 命令任务

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

我想我对这一切都错了。 结合以下两件事可能是最好的方法。

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

TestMethod现在是一个集成测试,而不是单元测试,因为它依赖于命令行参数。

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

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

...然后这将TestMethod转换为单元测试,其中IArgumentsProvider可以被IArgumentsProvider ,以便只测试TestMethod的功能(这是单元测试的定义)。

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM