dotnet test/run have inconsistent CWD
From @yoshiya8 on Monday, 27 August 2018 15:10:42
Steps to reproduce
Create a .NET core app that simply prints out the current directory from the environment and a .NET core XUNIT test case that does the same:
using System;
namespace DotnetRun
{
class Program
{
static void Main(string[] args) => Console.WriteLine($"CWD: [{Environment.CurrentDirectory}]");
}
}
and
using System;
using Xunit;
using Xunit.Abstractions;
namespace DotnetTest
{
public class UnitTest1
{
private readonly ITestOutputHelper output;
public UnitTest1(ITestOutputHelper output) => this.output = output;
[Fact]
public void Test1() => output.WriteLine($"CWD: [{Environment.CurrentDirectory}]");
}
}
- Run the app:
dotnet run - Note the output of the app.
- Run the unit test with logging to capture the output:
dotnet test --logger "trx;LogFileName=C:\some\path\Results.trx" - Get the output from the unit test:
Select-String -Path C:\some\path\Results.trx -Pattern "<StdOut>"
Expected behavior
The current directory for each run would be the current directory of the shell that launched the dotnet command.
Actual behavior
The current directory of the dotnet run is as expected. However, the current directory of the dotnet test is the directory of the .dll file ("$pwd\bin\Debug\netcorapp2.0")
Copied from original issue: dotnet/cli#9896
From @yoshiya8 on Monday, 27 August 2018 15:11:48
I believe this relates to: https://github.com/dotnet/cli/issues/4473
From @peterhuene on Friday, 03 May 2019 21:28:53
I finally got around to tracking down the source of the discrepancy between dotnet run and dotnet test. Neither commands in the CLI set the current working directory.
The culprit is the test host manager that is spawning the test host and explicitly setting the working directory to the directory containing the test assembly.
I'll move this issue there.
dotnet test users are expecting the CWD of their test code to be where dotnet test is running. However, the test host manager (see link in my previous comment) is explicitly changing the CWD to the directory containing the test dll.
As this isn't a dotnet test CLI command issue, but an issue with the test tools, I've moved the CLI issue here for you to decide on the correct behavior.
@yoshiya8 This is my design. This is the code responsible for this behavior https://github.com/Microsoft/vstest/blob/f33bb21b47b027016959d8385e0f69a7e3ff8027/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs#L234
Note that dotnet run and dotnet test are independent verbs. dotnet test invokes the test platform, and test platform runs the tests in isolation, making sure all the dependencies are loaded correctly. The test platform sets the source directory as the working directory for the test host where the actual execution happens. Hence the behavior you observed.
Can you please explain your scenario, so we can suggest something. Thanks.
It's a shame this has been closed. I still think this issue is valid.
When users call System.IO.Directory.GetCurrentDirectory() they expect to get the current directory. In other words the one that was current when executing the command, dotnet test. This is neither the output directory nor the source directory. It tends to be the solution directory. It's inconsistent with run and inconsistent with expected behaviour of GetCurrentDirectory().
Also, regarding the code, sourceDirectory is not correct either as I believe it's actually the proj directory which, by default is copied to the output dir anyway which is why CWD ends up being the output dir.
If you want a specific scenario, mine is that I have 2 ways to run my tests. dotnet test for CI and dotnet run tests which gives prettier output for local dev work. The tests rely on some data in the project but I can't rely on GetCurrentDirectory() if I want the CI dotnet test to work.
Please consider reopening this. Thanks.
@nohwnd FYI. We might want to reconsider this one.
@pavelhorak should we add this to 16.8?
IMHO, for unit tests it is preferred to reduce the impact of the environment, including the current working directory of the build scripts. If a unit test needs to tests some code that is dependent on the CWD, the test should explicitly set CWD, not depend on the external scripts to use specific directories. I think the current behavior causes less issues then the suggested modification.
+1 to operate like run.
Here's my current workflow: Run dotnet test in a test project directory using XUnit to run tests. I need to execute the tests from the test project directory (or a fixed known place) so that relative paths I need match up. The tests are end to end tests, so need to hit various files and executables.
My current workaround is to get the Test DLL path and change working dir based on it.
var dllPath = System.Reflection.Assembly.GetExecutingAssembly().Location;
Console.WriteLine($"DLL Path: {dllPath}");
var newPath = Path.Combine(dllPath, "../../../..");
System.IO.Directory.SetCurrentDirectory(newPath);
Console.WriteLine($"Current Dir: {Directory.GetCurrentDirectory()}");
I just got bitten by this, I expected it to operate like dotnet run, All my code is set to copy the things I need to the output directory, but when you do dotnet test, it doesn't use the output directory so nothing works.
I just came across this too. While the argument that the test environment shouldn't impact the tests is completely valid for unit tests, for integration tests and bechmarking it is just the opposite. We often want to run the same set of tests with different environment configurations.