Як отримати каталог під час запуску модульного тесту


78

Привіт, під час запуску мого модульного тесту я хочу отримати каталог, в якому працює мій проект, щоб отримати файл.

Скажімо, у мене є тестовий проект на ім’я MyProject. Тест, який я запускаю:

AppDomain.CurrentDomain.SetupInformation.ApplicationBase

і я отримую "C:\\Source\\MyProject.Test\\bin\\Debug".

Це близько до того, що я шукаю. Я не хочу bin\\Debugроль.

Хтось знає, як замість цього я міг отримати "C:\\Source\\MyProject.Test\\"?


1
Отже, якщо ми вас правильно зрозуміли, у вас є файл у вашому проекті, і ви хочете отримати файл під час запуску тесту програми / модуля?
abhilash

11
Також - вам краще отримати розташування таким чиномPath.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
abhilash

Так, я хочу отримати файл під час запуску модульного тесту
AnonyMouse

Відповіді:


71

Я б зробив це інакше.

Я пропоную зробити цей файл частиною рішення / проекту. Потім клацніть правою кнопкою миші -> Властивості -> Копіювати на вихід = Копіювати завжди.

Потім цей файл буде скопійовано в будь-який вихідний каталог (наприклад, C: \ Source \ MyProject.Test \ bin \ Debug).

Редагувати: Копіювати на вихід = Копіювати, якщо кращий варіант - Новіше


3
І НЕ ЗАБУВАЙТЕ, що вам також потрібно встановити для "Дії побудови" значення NONE.
Jiří Herník

3
Питання про те, як скопіювати файл у вихідну папку під час побудови, відрізняється від заданого.
Рік О'Ші

9
@ RickO'Shea Оригінальне запитання було проблемою XY . Автор запитання пояснив, що він хотів зробити у своєму коментарі - "Так, я хочу отримати файл під час запуску модульного тесту". Я просто запропонував рішення його фактичної проблеми (а не його спроби вирішити).
Ilian Pinzon 02

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

42

Зазвичай ви отримуєте каталог рішення (або каталог проекту, залежно від структури рішення) таким чином:

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

Це дасть вам батьківський каталог папки "TestResults", створену тестуючими проектами.


9
Відповідь 2016: Path.GetDirectoryName (Path.GetDirectoryName (TestContext.CurrentContext.TestDirectory))
DavidActualX

6
TestDir позначено як застарілий (2016), подумайте про використання TestContext.TestRunDirectory.
uli78

3
Що це таке TestContext.TestDir?
Кікенет,

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
Обидва режими налагодження та випуску ... Ваш код не відповідає меті моєї відповіді.
Джеремі Томпсон,

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

Так, вибачте за це. Я виправив форматування і додав приклад.
AHM

Або ви можете зробити щось подібне: Path.GetFullPath (AppDomain.CurrentDomain.SetupInformation.ApplicationBase + ".. \\ .. \\ .. \\")
Зар Шардан

1
AppDomain.CurrentDomain.BaseDirectory + @ "\ .. \ .. \ Images \ test.jpg", наприклад, працює для мене
Марті

Це не працює, він просто додає ".. \ .. \" до рядка. Вам потрібно зробити щось на зразок 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надасть вам шлях до тестового проекту Unit.

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 є багато змін. Я запропоную прочитати документацію про "Порушення змін"

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.