运行单元测试时如何获取目录


76

嗨,当我运行单元测试时,我想获取我的项目正在运行的目录以检索文件。

假设我有一个名为MyProject的测试项目。测试我运行:

AppDomain.CurrentDomain.SetupInformation.ApplicationBase

我收到了"C:\\Source\\MyProject.Test\\bin\\Debug"

这接近我的追求。我不希望bin\\Debug部分。

有人知道我怎么能得到"C:\\Source\\MyProject.Test\\"吗?


1
因此,如果我们对您的理解正确,那么您的项目中就有一个文件,并且您想在运行应用程序/单元测试时检索该文件?
abhilash 2012年

11
另外-您最好以这种方式获得位置Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
abhilash 2012年

是的,我想在运行单元测试时检索文件
AnonyMouse

Answers:


69

我会做不同的事情。

我建议将该文件作为解决方案/项目的一部分。然后右键单击->属性->复制到输出=始终复制。

然后,该文件将被复制到您的输出目录中(例如C:\ Source \ MyProject.Test \ bin \ Debug)。

编辑:复制到输出=复制,如果较新是更好的选择


3
并且不要忘记,您还需要将“ Build action”设置为NONE。
吉日Herník

3
在构建时如何将文件复制到输出文件夹的问题与所问的问题不同。
里克·奥谢

8
@ RickO'Shea最初的问题是XY问题。询问者在评论中阐明了他想做的事情-“是的,我想在运行单元测试时检索文件”。我只是为他的实际问题提供了解决方案(而不是他尝试的解决方案)。
Ilian Pinzon

8
我也使用了这种Copy To Output技术,并且在单独运行单元测试时它确实起作用。但是,从有序测试的上下文中运行它们时,它不起作用。我收到一个错误,例如:System.IO.FileNotFoundException: Could not find file 'C:\SVN\MyProject\TestResults\myName_MACHINE 2017-04-26 12_44_09\Out\MySpreadsheet.xlsx 显然创建了一个不同的子目录来保存测试结果,以及IDK为什么我的执行代码会在那儿查找
。.– bkwdesign

1
@IlianPinzon您不能调用任何不同意XY问题的解决方案。;)这是一个有效的问题,应该直接给出答案。
Extragorey

41

通常,您可以按以下方式检索解决方案目录(或项目目录,具体取决于您的解决方案结构):

string solution_dir = Path.GetDirectoryName( Path.GetDirectoryName(
    TestContext.CurrentContext.TestDirectory ) );

这将为您提供由测试项目创建的“ TestResults”文件夹的父目录。


9
2016年答案:Path.GetDirectoryName(Path.GetDirectoryName(TestContext.CurrentContext.TestDirectory))
DavidActualX 2016年

6
TestDir被标记为已弃用(2016年),请考虑使用TestContext.TestRunDirectory。
uli78 '16

3
什么TestContext.TestDir
Kiquenet

5
这不适用于xUnit。使用Path.GetDirectoryName(Assembly.GetExecutingAssembly()。Location)
zezba9000

1
实际上不推荐使用TestContext!
罗伦佐·伊西多里


11

除了@abhilash的评论。

这可以在我的EXE,DLL在调试或发布模式下从另一个UnitTest项目进行测试时起作用:

var dirName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location.Replace("bin\\Debug", string.Empty));

3
这是正确的,但简单的答案是:Path.GetDirectoryName(Assembly.GetExecutingAssembly()。Location)
zezba9000

1
Debug和Release模式都...您的代码违背了我的回答。
杰里米·汤普森

8
/// <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));
}

+1这个Assert.IsTrue(System.IO.Directory.Exists(directory));想法。我适应了它并使用了Assert.That(System.IO.Directory.Exists(directory), Is.True);。同样的东西,但更具可读性
RSM

6

我通常这样做,然后将其添加"..\..\"到所需目录中。

因此,您可以做的是:

var path = AppDomain.CurrentDomain.SetupInformation.ApplicationBase + @"..\..\";

不确定如何将“ .. \ .. \”添加到AppDomain.CurrentDomain.SetupInformation.ApplicationBase来转到目录
AnonyMouse 2012年

是的,对此感到抱歉。我修复了格式并添加了一个示例。
AHM 2012年

或者,您可以执行以下操作:Path.GetFullPath(AppDomain.CurrentDomain.SetupInformation.ApplicationBase +“ .. \\ .. \\ .. \\”)
Zar

1
AppDomain.CurrentDomain.BaseDirectory + @“ \ .. \ .. \ Images \ test.jpg”例如对我
Marty 2014年

这是行不通的,它只会在字符串后附加“ .. \ .. \”。您需要执行类似Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase,@“ .. \ .. \ .. \”,“ project \\ fille.json”))的操作;
达米安·格林

4

对于NUnit,这就是我的工作:

// 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;

如果需要,您可以从那里导航回其他目录(如果需要):

dir = Path.Combine(dir, "MySubDir");

谢谢,这几乎对我有用。因为NUnit.Framework.TestContext.CurrentContext.TestDirectory回报我必须上三个级别{pathToSolution}\TestProject\bin\Debug\netcoreapp2.2。也AppContext.BaseDirectory返回相同的东西。
德鲁

其实没关系,AppContext.BaseDirectory与NUnit属性相比,它具有一个尾随反斜杠,需要额外增加一个级别。
提请


1

我发现最好的解决方案是将文件作为嵌入式资源放在测试项目中,并从单元测试中获取它。使用此解决方案,我不需要关心文件路径。


1

通常,无论运行测试或控制台应用程序还是网络应用程序,都可以使用此方法:

// 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;

如果您正在运行NUnit,则:

// return the absolute path of directory, i.e. C:\...\
var testDirectory = TestContext.CurrentContext.TestDirectory;

1

我的方法依赖于获取单元测试组件的位置,然后向上遍历。在以下代码段中,变量folderProjectLevel将为您提供单元测试项目的路径。

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 + "..\\..\\");

0

您可以这样做:

using System.IO;

Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, @"..\..\"));

0

根据https://github.com/nunit/nunit/issues/742#issuecomment-121964506

对于NUnit3,永远不要更改System.Environment.CurrentDirector,因此它应该是解决方案的路径。

例如:

string szProjectPath = System.Environment.CurrentDirectory + @"\where\your\project\is";

我更喜欢固定位置而不是GetParent()。GetParent的一个缺点是,当构建从AnyCPU更改为x86时,默认路径将从bin \ Debug更改为bin \ x86 \ Debug。需要另一个父母,这是脖子上的痛苦。

此外,您仍然可以通过访问测试程序集TestContext.CurrentContext.TestDirectory

编辑:注意:NUnit3中有许多更改。我建议您通读有关“重大更改”的文档

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.