Visual Studio - модульные тесты загружают ресурсы в проект
Цель состоит в том, чтобы запустить некоторые тесты с учетом некоторых данных в этих файлах Xml.
Как бы вы легко загрузили данный Xml файл в XmlDoc в методы unit test?
Текущее состояние:
XmlDocument doc = new XmlDocument();
string xmlFile = "4.xml";
string dir = System.IO.Directory.GetCurrentDirectory() + @"\Msgs\"
//dir is then the value of the current exe path, which is
//d:\sourcecode\myproject\TestResults\myComputer 2009-10-08 16_07_45\Out
//we actually need:
//d:\sourcecode\myproject\Msgs\
doc.Load( dir + fileName); //should really use System.IO.Path.Combine()!
Это просто вопрос размещения этого пути в app.config
? Я надеялся избежать этого, учитывая возможность различных путей на машинах для разработчиков.
Вопрос: Как вы напишете алгоритм для загрузки данного Xml файла в XmlDocument в методе unit test?
Ответы
Ответ 1
В проекте unit test добавьте событие post-build, которое копирует XML файл в выходной каталог. Затем вы можете использовать свой исходный код для получения XML файла.
Событие post build будет выглядеть примерно так:
copy $(SolutionDir)file.xml $(ProjectDir)$(OutDir)file.xml
Вам также может понадобиться это, чтобы добавить к вашему пути:
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
Ответ 2
Для этого есть функция тестирования модуля Visual Studio: DeploymentItemAttribute
Я использую эту функцию, чтобы скопировать все xml файлы в данной папке проекта в папку вывода unit test, прежде чем тестировать, присутствуют ли все необходимые файлы.
Этот атрибут можно использовать с модульными тестами для копирования определенных файлов из папки "Проект" (или в другое место) в папку вывода unit test. Например:
[TestMethod()]
[DeploymentItem("MyProjectFolder\\SomeDataFolder\\somefile.txt", "SomeOutputSubdirectory")]
public void FindResourcefile_Test()
{
string fileName = "SomeOutputSubdirectory\\somefile.txt";
Assert.IsTrue(System.IO.File.Exists(fileName));
}
Вы также можете скопировать содержимое целых папок:
[TestMethod()]
[DeploymentItem("MyProjectFolder\\SomeDataFolder\\", "SomeOutputSubdirectory")]
public void FindResourcefile_Test()
{
string fileName = "SomeOutputSubdirectory\\someOtherFile.txt";
Assert.IsTrue(System.IO.File.Exists(fileName));
}
Первым параметром является источник, второй - папка назначения. Источник относится к папке вашего решения (так что вы можете получить доступ к проекту unit test тестируемого проекта), а пункт назначения относится к выходной папке сборки unit test.
UPDATE:
Для этого вам необходимо включить развертывание в настройках тестирования. На этой странице MSDN объясняется, как (это очень легко): http://msdn.microsoft.com/en-us/library/ms182475(v=vs.90).aspx#EnableDisableDeploy
Ответ 3
Вы можете скомпилировать эти файлы в свой исполняемый файл (установите для своего свойства Build Action значение "Embedded Resource" ), а затем получите их с помощью Assembly.GetManifestResourceStream method
.
Ответ 4
Я использую класс-помощник, чтобы иметь дело с получением базовых путей, которые я мог бы получить в своих модульных тестах.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Brass9.Testing
{
public static class TestHelper
{
public static string GetBinPath()
{
return System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
}
public static string GetProjectPath()
{
string appRoot = GetBinPath();
var dir = new DirectoryInfo(appRoot).Parent.Parent.Parent;
var name = dir.Name;
return dir.FullName + @"\" + name + @"\";
}
public static string GetTestProjectPath()
{
string appRoot = GetBinPath();
var dir = new DirectoryInfo(appRoot).Parent.Parent;
return dir.FullName + @"\";
}
public static string GetMainProjectPath()
{
string testProjectPath = GetTestProjectPath();
// Just hope it ends in the standard .Tests, lop it off, done.
string path = testProjectPath.Substring(0, testProjectPath.Length - 7) + @"\";
return path;
}
}
}
Иногда мои взаимодействия с путями более сложны; Я часто использую центральный класс, который я называю "App", чтобы указать некоторые основные сведения о приложении, такие как его корневая папка, его корневое пространство имен и модуль и т.д. Классы будут иногда зависеть от существования App, и поэтому вместо этого я поставлю init метод в приложении, который использует код, подобный приведенному выше, для инициализации для тестовых жгутов и вызов этого метода из команды Init в Unit Test.
(обновлено)
Старый ответ
Я нашел, что это помогает получить произвольные пути для доступа к файлам в папке проекта, которую вы собираетесь тестировать (в отличие от файлов в папке Test project, которая может работать, если вам нужно скопировать вещи).
DirectoryInfo projectDir = new DirectoryInfo(@"..\..\..\ProjectName");
string projectDirPath = projectDir.FullName;
Затем вы можете использовать любую из этих переменных для доступа к тому, что вам нужно от соответствующего проекта. Очевидно, замените "ProjectName" на фактическое название вашего проекта.
Ответ 5
Ресурсы - это просто ресурсы и что это не нужно усложнять. Если вы не хотите их внедрять, вы можете добавить эти файлы в качестве ресурсов "Контент" в свой проект и установить их в Copy always
. Затем укажите подкаталог в вашем коде:
var xmlDoc = XElement.Load("ProjectSubFolder\\Resource.xml");
Это автоматически загрузит ресурсы из выходных данных проекта (запуск сборки) bin\$(Configuration)\ResourceSubfolder\
Это работает для всех типов проектов, а не только для модульных тестов.
Ответ 6
Я бы просто поместил путь в app.config и загрузился с пути по умолчанию. В моей команде я действительно анал о том, что разработчики меняют пути, поэтому я заставляю всех своих разработчиков иметь одинаковые точные пути и файлы на своих компьютерах, поэтому у меня нет проблемы с каким-либо разработчиком-изгоев, который меняет путь к набору своего рабочего пространства.
Например, все разработчики в моей команде должны использовать C:\Project\Product\Module и т.д. и т.д. Также я уверен, что все их программное обеспечение также стандартно. Таким образом, я могу призвать любую машину в любой другой.
Ответ 7
Я думаю, что в VS.NET 2012 атрибут DeploymentItem работает без конфигурации тестовых настроек.