Reputation: 18630
When running my unit test, I want to get the directory my project is running. Then I can retrieve a file.
Say I have a Test project named MyProject. Test I run:
AppDomain.CurrentDomain.SetupInformation.ApplicationBase
and I receive "C:\\Source\\MyProject.Test\\bin\\Debug"
.
This is close to what I'm after. I don't want the bin\\Debug
part.
Anyone know how instead I could get "C:\\Source\\MyProject.Test\\"
?
Upvotes: 106
Views: 135978
Reputation: 11
This is my solution to get the location by recursion
internal static class PathUtil
{
internal static string GetRoot()
{
var binFolder = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
var assemblyName = Assembly.GetCallingAssembly().GetName().Name;
return Reduce(binFolder, assemblyName!)};
}
private static string Reduce(string? path, string lastFolder) => path switch
{
not null when path.EndsWith(lastFolder) => path,
not null when path == string.Empty => ".\\",
not null => Reduce(Path.GetDirectoryName(path), lastFolder),
_ => ".\\"
};
}
Upvotes: 0
Reputation: 2588
According to https://github.com/nunit/nunit/issues/742#issuecomment-121964506
For NUnit3 , System.Environment.CurrentDirector is never changed, so it shall be the path of solution.
Eg:
string szProjectPath = System.Environment.CurrentDirectory + @"\where\your\project\is";
I prefer fixed location rather than GetParent(). One drawback of GetParent is when build is changed from AnyCPU to x86, default path would be changed from bin\Debug to bin\x86\Debug. Need to get another parent, and it's pain in the neck.
Also, you may still access to you test assemblies at TestContext.CurrentContext.TestDirectory
and get output from TestContext.CurrentContext.WorkDirectory
Edit: Note: There are many changes in NUnit3. I will suggest reading through the documentation about "Breaking changes"
Upvotes: 4
Reputation: 1
use StackTrace
internal static class Extensions
{
public static string GetSourceDirectoryName(this Type type)
{
StackTrace stackTrace = new StackTrace(true);
foreach (var frame in stackTrace.GetFrames())
{
if (frame.GetMethod() is { } method && method.DeclaringType == type)
{
return Path.GetDirectoryName(frame.GetFileName());
}
}
throw new Exception($"未找到{type.Name}源文件目录");
}
}
Upvotes: 0
Reputation: 5355
I would do it differently.
I suggest making that file part of the solution/project. Then right-click -> Properties -> Copy To Output = Copy Always.
That file will then be copied to whatever your output directory is (e.g. C:\Source\MyProject.Test\bin\Debug).
Edit: Copy To Output = Copy if Newer is the better option
Upvotes: 92
Reputation: 6186
Usually you retrieve your solution directory (or project directory, depending on your solution structure) like this:
string solution_dir = Path.GetDirectoryName( Path.GetDirectoryName(
TestContext.CurrentContext.TestDirectory ) );
This will give you the parent directory of the "TestResults" folder created by testing projects.
Upvotes: 57
Reputation: 1664
My approach relies on getting the location of the unit testing assembly and then traversing upwards. In the following snippet the variable folderProjectLevel
will give you the path to the Unit test project.
string pathAssembly = System.Reflection.Assembly.GetExecutingAssembly().Location;
string folderAssembly = System.IO.Path.GetDirectoryName(pathAssembly);
if (folderAssembly.EndsWith("\\") == false) {
folderAssembly = folderAssembly + "\\";
}
string folderProjectLevel = System.IO.Path.GetFullPath(folderAssembly + "..\\..\\");
Upvotes: 1
Reputation: 65554
Further to @abhilash's comment.
This works in my EXE's, DLL's and when tested from a different UnitTest project in both Debug or Release modes:
var dirName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location.Replace("bin\\Debug", string.Empty));
Upvotes: 12
Reputation: 69968
You can do it like this:
using System.IO;
Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, @"..\..\"));
Upvotes: 0
Reputation: 710
In general you may use this, regardless if running a test or console app or web app:
// returns the absolute path of assembly, file://C:/.../MyAssembly.dll
var codeBase = Assembly.GetExecutingAssembly().CodeBase;
// returns the absolute path of assembly, i.e: C:\...\MyAssembly.dll
var location = Assembly.GetExecutingAssembly().Location;
If you are running NUnit, then:
// return the absolute path of directory, i.e. C:\...\
var testDirectory = TestContext.CurrentContext.TestDirectory;
Upvotes: 1
Reputation: 15055
For NUnit this is what I do:
// Get the executing directory of the tests
string dir = NUnit.Framework.TestContext.CurrentContext.TestDirectory;
// Infer the project directory from there...2 levels up (depending on project type - for asp.net omit the latter Parent for a single level up)
dir = System.IO.Directory.GetParent(dir).Parent.FullName;
If required you can from there navigate back down to other directories if required:
dir = Path.Combine(dir, "MySubDir");
Upvotes: 4
Reputation: 699
/// <summary>
/// Testing various directory sources in a Unit Test project
/// </summary>
/// <remarks>
/// I want to mimic the web app's App_Data folder in a Unit Test project:
/// A) Using Copy to Output Directory on each data file
/// D) Without having to set Copy to Output Directory on each data file
/// </remarks>
[TestMethod]
public void UT_PathsExist()
{
// Gets bin\Release or bin\Debug depending on mode
string baseA = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
Console.WriteLine(string.Format("Dir A:{0}", baseA));
Assert.IsTrue(System.IO.Directory.Exists(baseA));
// Gets bin\Release or bin\Debug depending on mode
string baseB = AppDomain.CurrentDomain.BaseDirectory;
Console.WriteLine(string.Format("Dir B:{0}", baseB));
Assert.IsTrue(System.IO.Directory.Exists(baseB));
// Returns empty string (or exception if you use .ToString()
string baseC = (string)AppDomain.CurrentDomain.GetData("DataDirectory");
Console.WriteLine(string.Format("Dir C:{0}", baseC));
Assert.IsFalse(System.IO.Directory.Exists(baseC));
// Move up two levels
string baseD = System.IO.Directory.GetParent(baseA).Parent.FullName;
Console.WriteLine(string.Format("Dir D:{0}", baseD));
Assert.IsTrue(System.IO.Directory.Exists(baseD));
// You need to set the Copy to Output Directory on each data file
var appPathA = System.IO.Path.Combine(baseA, "App_Data");
Console.WriteLine(string.Format("Dir A/App_Data:{0}", appPathA));
// C:/solution/UnitTestProject/bin/Debug/App_Data
Assert.IsTrue(System.IO.Directory.Exists(appPathA));
// You can work with data files in the project directory's App_Data folder (or any other test data folder)
var appPathD = System.IO.Path.Combine(baseD, "App_Data");
Console.WriteLine(string.Format("Dir D/App_Data:{0}", appPathD));
// C:/solution/UnitTestProject/App_Data
Assert.IsTrue(System.IO.Directory.Exists(appPathD));
}
Upvotes: 9
Reputation: 103
The best solution I found was to put the file as an embedded resource on the test project and get it from my unit test. With this solution I don´t need to care about file paths.
Upvotes: 2
Reputation: 900
Directory.GetParent(Directory.GetCurrentDirectory()).Parent.FullName;
This will give you the directory you need....
as
AppDomain.CurrentDomain.SetupInformation.ApplicationBase
gives nothing but
Directory.GetCurrentDirectory().
Have alook at this link
http://msdn.microsoft.com/en-us/library/system.appdomain.currentdomain.aspx
Upvotes: 38
Reputation: 5225
I normally do it like that, and then I just add "..\..\"
to the path to get up to the directory I want.
So what you could do is this:
var path = AppDomain.CurrentDomain.SetupInformation.ApplicationBase + @"..\..\";
Upvotes: 6
Reputation: 5701
I'm not sure if this helps, but this looks to be briefly touched on in the following question.
Visual Studio Solution Path environment variable
Upvotes: 1