Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing arguments to dotnet test project?

I have the test class below in a .NET Core 1.1 Unit Test project (not an xUnit Test project) in Visual Studio 2017. How do I pass command line arguments to TestMethod?

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

Lots of places on the internet make it sound like you can just put a -- in front of the arguments you want to pass in, but I can't get it to work.

These are the commands I've tried:

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

But all of them output this message every time. Note how neither hello nor world are present:

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

The first string is just the name of the running assembly -- pretty standard for the first command line argument. I don't know where the --port or --parentprocessid arguments are coming from.

Also, these variations make dotnet test choke with One or more runsettings provided contain invalid token (sic):

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

Edit: It looks like GetCommandLineArgs() isn't that great of an option, even if it did work here.

Also, the answer to this question on social.msdn.microsoft.com from 2006 says:

The way those classes are instantiated so VS can do unit testing against them is entirely different than normal execution. The executable is not run like normal, and neither you nor VS can provide arguments to it. The classes are instantiated indepdently of program execution by using the binary as a class library. (sic)

I wonder if this still applies to dotnet test?

In other news, this guy on SO was doubtful that command line arguments could be passed to DLLs at all, but he's wrong:

[Prototype for the <entrypoint> function:] void CALLBACK EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);

[Rundll] calls the <entrypoint> function, passing the command line tail which is the <optional arguments>.

like image 898
Matt Thomas Avatar asked Mar 24 '17 05:03

Matt Thomas


People also ask

How do you pass command line arguments in dotnet run?

To pass arguments to your application, you need to pass a -- argument, and then the arguments to your application. As per the . NET Core CLI documentation, -- delimits arguments to dotnet run from arguments for the application being run. All arguments after this one are passed to the application run.

How does dotnet test find tests?

The dotnet test command builds the solution and runs a test host application for each test project in the solution. The test host executes tests in the given project using a test framework, for example: MSTest, NUnit, or xUnit, and reports the success or failure of each test.

How do I pass arguments to a DotNet application?

To pass arguments to your application, you need to pass a -- argument, and then the arguments to your application. As per the .NET Core CLI documentation, -- delimits arguments to dotnet run from arguments for the application being run.

How do I run a DotNet test from a project?

Examples 1 Run the tests in the project in the current directory: .NET Core CLI dotnet test 2 Run the tests in the test1 project: .NET Core CLI dotnet test ~/projects/test1/test1.csproj 3 Run the tests in the project in the current directory, and generate a test results file in the trx format: .NET Core CLI dotnet test --logger trx More items...

How to pass environment variables into the DotNet test command?

It's possible to pass environment variables into the dotnet test command via the --environment parameter with dotnet/sdk#13436. --launch-profile support is on hold for the time being because it's part of the dotnet run command and needs some more development by its owners; we'll implement the support on the dotnet test after the work is done.

How to get command line arguments from interface in TestMethod?

A blend of the below two things is probably the best approach. TestMethod as it is now is an integration test, not a unit test, because it depends on command line arguments. If I refactor TestMethod so that it gets the command line arguments from an interface like this: interface IArgumentsProvider { IEnumerable<string> GetArguments (); }


2 Answers

You can pass Runsettings to the test runner like this (example for bash):

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

For other shell types this is obviously a question of correct escaping which might be a pain as you will see. For MSTest the parameters are accessible via

var args = TestContext.Properties["YourTestProject.Args"].Split();
like image 192
Paul Michalik Avatar answered Oct 21 '22 10:10

Paul Michalik


This is one of the places I encountered while searching for this answer, so it's only fair I share my workaround here.

At this moment, there is no way to pass parameters to any .net test project. You could use the mstest testsettings/runsettings file, but that requires creating seperate files. In my case, I needed a servername and a password for my Selenium Coded UI tests, and I did not want to store them.

One of the recommended ways of passing parameters, is through environment variables. So in your C# xunit file, you can do something like:

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

If you do not want to definitively set your environment variables, remember you can always set them temporarily for just your session process. One way of doing this, is by creating a simple cmd file

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

And now the fun part. You can parameterize every aspect of this. So you can change it to:

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

Or if you want to launch the test from an Azure DevOps (fka VSTS or TFS) pipeline, you can simply use the $(...) notation to inline variables, even if they're marked secret and/or come from 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

like image 30
realbart Avatar answered Oct 21 '22 11:10

realbart