vstest icon indicating copy to clipboard operation
vstest copied to clipboard

dotnet test/run have inconsistent CWD

Open peterhuene opened this issue 6 years ago • 11 comments

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}]");
    }
}
  1. Run the app: dotnet run
  2. Note the output of the app.
  3. Run the unit test with logging to capture the output: dotnet test --logger "trx;LogFileName=C:\some\path\Results.trx"
  4. 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

peterhuene avatar May 03 '19 21:05 peterhuene

From @yoshiya8 on Monday, 27 August 2018 15:11:48

I believe this relates to: https://github.com/dotnet/cli/issues/4473

peterhuene avatar May 03 '19 21:05 peterhuene

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.

peterhuene avatar May 03 '19 21:05 peterhuene

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.

peterhuene avatar May 03 '19 21:05 peterhuene

@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.

singhsarab avatar May 04 '19 10:05 singhsarab

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.

PhilT avatar May 01 '20 10:05 PhilT

@nohwnd FYI. We might want to reconsider this one.

singhsarab avatar May 02 '20 21:05 singhsarab

@pavelhorak should we add this to 16.8?

nohwnd avatar May 04 '20 10:05 nohwnd

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.

bantolov avatar Nov 20 '20 09:11 bantolov

+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()}");

gregberns avatar Nov 20 '20 17:11 gregberns

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.

trampster avatar Mar 04 '21 23:03 trampster

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.

andradf avatar Jan 19 '22 16:01 andradf