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>.
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.
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.
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.
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...
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.
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 (); }
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();
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With