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

时间:2017-03-24 05:38:01

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

我在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:\用户\ ____ \的NuGet \包\ microsoft.testplatform.testhost \ 15.0.0 \ lib中\ netstandard1.5 \ testhost.dll"" - 端口& #34;" 55032"" - parentprocessid"" 24440"]

第一个字符串只是正在运行的程序集的名称 - 非常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

  

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

     

[Rundll]调用< entrypoint> function,传递命令行尾,这是<可选参数>。

3 个答案:

答案 0 :(得分:2)

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

目前,尚无法将参数传递给任何.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)

run Azure DevOps command task

答案 1 :(得分:0)

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

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

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

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

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

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

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

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

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

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

答案 2 :(得分:0)

您可以像这样将运行设置传递给测试运行程序(bash示例):

const myObj = new CustomObject({ name: [], age: 0, country: "" });
const valid = myObj.isValid({
  name: ["John", "Doe"],
  age: 25,
  country: "Hungary",
});

console.log(valid); // returns true

对于其他外壳类型,这显然是正确转义的问题,您可能会发现这很痛苦。对于MSTest,可以通过

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