C# Unit testing - Weird project directory - c#

I have a situation where I am running a unit test and trying to get the project base path and it is giving me a odd output.
D:\VSCode\Bob.Smith\Projects\MySolution\DEVELOPMENT\MyClasses\MyProject\TestResults\Jacob.Freeman_P1004 2012-11-26 09_21_33\Out
Is this a known issue with VS or just something that I have missed out? I am using the following line with no other code to get the directory information.
string output = null;
output = Environment.CurrentDirectory;
I have tried different various ways to get the directory information such as the following, but it still gives me the same output.
output = System.IO.Directory.GetCurrentDirectory()
Thanks in advance.

As documentation states Environment.CurrentDirectory:
Gets or sets the fully qualified path of the current working directory.
The current working directory is not necessarily the projects base path - It is when you start an exe. While running test this path is set by test runner. This variable can change while program is running.
In application you should use Assembly.GetEntryAssembly().Location to get location of you exe file. This will not work for tests as they are executed by test runner.
If for test purposes you simply need location of tested dll file you can use typeof(SomeTypeThatIsDeclaredInThatDLL).Assembly.Location.

It works as designed. Your tests executes in different directory against bin.

Related

How do I keep my application's working directory consistent even when being run from a batch file? [duplicate]

I see that there are some ways to get the application folder path:
Application.StartupPath
System.IO.Path.GetDirectoryName(
System.Reflection.Assembly.GetExecutingAssembly().Location)
AppDomain.CurrentDomain.BaseDirectory
System.IO.Directory.GetCurrentDirectory()
Environment.CurrentDirectory
System.IO.Path.GetDirectoryName(
System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase)
System.IO.Path.GetDirectory(Application.ExecutablePath)
What is the best way depending on the situation?
AppDomain.CurrentDomain.BaseDirectory is probably the most useful for accessing files whose location is relative to the application install directory.
In an ASP.NET application, this will be the application root directory, not the bin subfolder - which is probably what you usually want. In a client application, it will be the directory containing the main executable.
In a VSTO 2005 application, it will be the directory containing the VSTO managed assemblies for your application, not, say, the path to the Excel executable.
The others may return different directories depending on your environment - for example see #Vimvq1987's answer.
CodeBase is the place where a file was found and can be a URL beginning with http://. In which case Location will probably be the assembly download cache. CodeBase is not guaranteed to be set for assemblies in the GAC.
UPDATE
These days (.NET Core, .NET Standard 1.3+ or .NET Framework 4.6+) it's better to use AppContext.BaseDirectory rather than AppDomain.CurrentDomain.BaseDirectory. Both are equivalent, but multiple AppDomains are no longer supported.
Application.StartupPathand 7. System.IO.Path.GetDirectoryName(Application.ExecutablePath) - Is only going to work for Windows Forms application
System.IO.Path.GetDirectoryName(
System.Reflection.Assembly.GetExecutingAssembly().Location)
Is going to give you something like: "C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\Temporary ASP.NET Files\\legal-services\\e84f415e\\96c98009\\assembly\\dl3\\42aaba80\\bcf9fd83_4b63d101" which is where the page that you are running is.
AppDomain.CurrentDomain.BaseDirectory for web application could be useful and will return something like "C:\\hg\\Services\\Services\\Services.Website\\" which is base directory and is quite useful.
System.IO.Directory.GetCurrentDirectory() and 5. Environment.CurrentDirectory
will get you location of where the process got fired from - so for web app running in debug mode from Visual Studio something like "C:\\Program Files (x86)\\IIS Express"
System.IO.Path.GetDirectoryName(
System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase)
will get you location where .dll that is running the code is, for web app that could be "file:\\C:\\hg\\Services\\Services\\Services.Website\\bin"
Now in case of for example console app points 2-6 will be directory where .exe file is.
Hope this saves you some time.
Note that not all of these methods will return the same value. In some cases, they can return the same value, but be careful, their purposes are different:
Application.StartupPath
returns the StartupPath parameter (can be set when run the application)
System.IO.Directory.GetCurrentDirectory()
returns the current directory, which may or may not be the folder where the application is located. The same goes for Environment.CurrentDirectory. In case you are using this in a DLL file, it will return the path of where the process is running (this is especially true in ASP.NET).
For a web application, to get the current web application root directory, generally call by web page for the current incoming request:
HttpContext.Current.Server.MapPath();
System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath;
Above code description
I started a process from a Windows Service over the Win32 API in the session from the user which is actually logged in (in Task Manager session 1 not 0). In this was we can get to know, which variable is the best.
For all 7 cases from the question above, the following are the results:
Path1: C:\Program Files (x86)\MyProgram
Path2: C:\Program Files (x86)\MyProgram
Path3: C:\Program Files (x86)\MyProgram\
Path4: C:\Windows\system32
Path5: C:\Windows\system32
Path6: file:\C:\Program Files (x86)\MyProgram
Path7: C:\Program Files (x86)\MyProgram
Perhaps it's helpful for some of you, doing the same stuff, when you search the best variable for your case.
In my experience, the best way is a combination of these.
System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase
Will give you the bin folder
Directory.GetCurrentDirectory()
Works fine on .Net Core but not .Net and will give you the root directory of the project
System.AppContext.BaseDirectory and AppDomain.CurrentDomain.BaseDirectory
Works fine in .Net but not .Net core and will give you the root directory of the project
In a class library that is supposed to target.Net and .Net core I check which framework is hosting the library and pick one or the other.
To get the path to .exe for simple desktop applications I use
Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)
which returns path to .exe.
Also be aware that for several domains the .exe for default domain will be returned, or the .exe executed by first call of ExecuteAssembly(String) and that if the entry is unmanaged, the null will be returned.
Be careful with GetExecutingAssembly(), naming was confusing for me, as I have expected to get the .exe, but it returns the .dll or .exe, where the code is placed, so in case of GetExecutingAssembly() placed in library it returns the library.
I have used this one successfully
System.IO.Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName)
It works even inside linqpad.
Root directory:
DriveInfo cDrive = new DriveInfo(System.Environment.CurrentDirectory);
var driverPath = cDrive.RootDirectory;
If you know to get the root directory:
string rootPath = Path.GetPathRoot(Application.StartupPath)
this one System.IO.Path.GetDirectory(Application.ExecutablePath) changed to System.IO.Path.GetDirectoryName(Application.ExecutablePath)

Unit Testing, Current Directory and Application Path

When coding parts of an application that require access to a directory, I often write the code so that if the Directory is specified using a relative path, the system assumes that the intent is to use a directory subordinate to the directory/folder that the Application (Executable) is running in (or was loaded from).
But when I run Unit Tests which exercise this code, it turns out that the Application path is a completely different directory, because the "Application " is the Test runner Harness, and it is running in a separate directory.
For writes this is no problem, but if the code is attempting to read a file configured in the solution as [Content] from a directory that the compiler copied as part of the build process, this file is of course not in the Test Runner version of the folder at all.
This can be resolved for files that are physically in the test project solution space, (by adding additional instructions on TestRunner configuration), but as far as I know, if the file is specified in the Solution as a link to a physical file located outside the project space, then I have yet to be able to find a simple solution to the problem.
What solutions to this issue exist? and what are the pros/cons of each one?

Mono executes program with wrong current directory

I have a strange problem. I have written a custom spamfilter in C# .NET 4.6 for personal use. And I put this program up to my Raspberry Pi.
I have tested many times the program, and everything worked fine, but when I created a cronjob I have noticed that the program never writes log.
As I started to test again I have find out, that the problem is, when I start the program from the program's base dir, it works fine:
> cd path/to/program
> mono program.exe
but when I start it from another directory with absolute path:
> mono /absolute/path/to/program/program.exe
The required files' relative paths go wrong.
For example if I'm in the /home directory, and my program is in /home/user/program directory, and I run this:
> mono /home/user/program/program.exe
I get " Could not find file "/home/xyz.txt" "
I have tried to create absolute paths from relative paths in the program using Path.GetFullPath() and Environment.CurrentDirectory but nothing changed.
So my question is: Is there any option to run a mono program in another directory with correct current directory?
I know that a bash script could execute my first solution (cd and then mono) and it could be used in cron, but I want to know if there is a simplier solution.
The current directory is correct, it is the current directory of where you are starting the process, and that process is mono in this case, and not the location of the CIL-based assembly that mono is loading.
What it sounds like you want is the path of the ExecutingAssembly.
This works on x-plat (Windows/Linux/macOS):
string path = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase);
Console.WriteLine(path);
Ref: https://msdn.microsoft.com/en-us/library/aa457089.aspx

How to reference a file inside my Test project to load w/o hard coded the path?

In my nunit test project I have a layout like:
/Fixters/someFile.txt
/Services/SomeService.cs
someFile.txt is a file that I need to read as it contains text that I use for my unit tests.
How can I reference this folder without hard coding the path as other team members may store this project at a different path that me.
If you do File.ReadAllText(filepath) and any other equivalent method where you pass in a relative path, the runtime will use the app's current working directory to create the whole path. So generally speaking, you should be fine using relative paths. You might also need to specify that someFile.txt gets copied to the output directory.
If unsure what the cwd is, try Directory.GetCurrentDirectory()

Better way to get the base directory?

I have this code to load a config file and read all the values and it works fine when running the application but of course fails on team city because the appdomain's base directory is where the build script (psake) is started. I know I can change directory to the build dir before executing the tests but I thought it's better to make loading the config file work at all times regardless.
XDocument.Load(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, cfgFile));
Is there another way to get the "BaseDirectory" that really works all times? I tried the below as well with same results:
string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase);
XDocument.Load(Path.Combine(path, cfgFile));
EDIT 1 The problem is the following. My solutions base directory is "C:\Project", all compiled files are copied to "C:\Project\build". Now in the psake build script I have the following code:
task Test -depends PrepareTests {
try {
#$old = pwd
#cd $build_dir
&$mspec $mspec_projects --teamcity
#cd $old
}
catch {
&echo "Error starting test runner"
Exit 1;
}
}
As you can see I commented out the changing of directories which makes the BaseDirectory the location of the build file / solution instead of the build directory regardless of how I try to access it. Kind of confusing if you ask me.
UPDATE I really like to know if it is possible to get the directory of the assembly regardless of what directory the application that started the app domain is located. How?
differents ways to get the base directory
AppDomain.CurrentDomain.BaseDirectory
Directory.GetCurrentDirectory() // not guaranteed to work on Mobile application
Environment.CurrentDirectory // this calls Directory.GetCurrentDirectory()
this.GetType().Assembly.Location // Assembly.location
Application.StartupPath // for windows forms apps
Application.ExecutablePath // same as Application.StartupPath
string origAssemblyLocation = Assembly.GetExecutingAssembly().CodeBase;
Per MSDN:
Assembly.CodeBase Property
Gets the location of the assembly as
specified originally
Your question is a bit unclear. I don't really know if this is what you want.
I typically use AppDomain.CurrentDomain.BaseDirectory
Alternatives
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
Environment.CurrentDirectory
So it sounds/looks like you're attempting to obtain the configuration file for an assembly. The following should accomplish that task by accessing the 'Location' property of the assembly and using it to retrieve the configuration path:
static string GetConfigFileByType(Type type)
{
Configuration config =
ConfigurationManager.OpenExeConfiguration(type.Assembly.Location);
if (config.HasFile)
return config.FilePath;
throw new FileNotFoundException();
}
try this one:
Module[] modules = Assembly.GetExecutingAssembly().GetModules();
return Path.GetDirectoryName(modules[0].FullyQualifiedName);
have you tried getting the FileName of the current process' MainModule?
System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName
Or GetEntryAssembly()?
System.Reflection.Assembly.GetEntryAssembly().Location
I like to make my classes configurable - for example they get the folder name as a parameter in their constructor.
This makes it possible to test with different config files.
In test code we use:
TestContext.TestDeploymentDir
This is the testrun folder, where all assemblies for a test run are copied into, together with the test deployment items. We 'deploy' our unit test config files to the test run folder - this can be specified in the testrunconfig dialog in visual studio.
For our production code we pass
Assembly.GetExecutingAssembly().Location
to the constructor, which works for us.
how about:
Application.StartupPath;
string baseDirectory=Application.StartupPath.Split(Path.DirectorySeparatorChar)[0];
Application startup path will return the path where exe is kept, we will split this using "\" and get the base directory as "C:" for example,

Categories

Resources