[ACCEPTED]-Visual Studio - Unit tests loading resources in the project-filepath

Accepted answer
Score: 27

There is a Visual Studio Unit Testing feature 18 for this: DeploymentItemAttribute

I use this feature to copy all 17 xml files in a given project folder to the 16 unit test output folder, before testing 15 if all required files are present.

You can 14 use this attribute with your unit tests 13 to copy specific files from the Project 12 folder (or anywhere else) to the Unit Test 11 output folder. Like so:

[TestMethod()]
[DeploymentItem("MyProjectFolder\\SomeDataFolder\\somefile.txt", "SomeOutputSubdirectory")]
public void FindResourcefile_Test()
{
    string fileName = "SomeOutputSubdirectory\\somefile.txt";
    Assert.IsTrue(System.IO.File.Exists(fileName));
}

You can also copy 10 the contents of whole folders:

[TestMethod()]
[DeploymentItem("MyProjectFolder\\SomeDataFolder\\", "SomeOutputSubdirectory")]
public void FindResourcefile_Test()
{
    string fileName = "SomeOutputSubdirectory\\someOtherFile.txt";
    Assert.IsTrue(System.IO.File.Exists(fileName));
}

The first 9 parameter is the source, the second the 8 destination folder. The source is relative 7 to your solution folder (so you can access 6 the Unit Test project of the project being 5 tested) and the destination is relative 4 to the output folder of the unit test assembly.

UPDATE:

You 3 need to enable Deployment in the Test Settings 2 for this to work. This MSDN page explains 1 how (it's real easy): http://msdn.microsoft.com/en-us/library/ms182475(v=vs.90).aspx#EnableDisableDeploy

Score: 24

You can build those files into your executable 2 (set their "Build Action" property to "Embedded 1 Resource") and then get them using the Assembly.GetManifestResourceStream method.

Score: 11

In the unit test project add a post-build 5 event that copies the XML file to the output 4 directory. Then, you can use your original 3 code to get the XML file.

The post build 2 event will look like something like this:

copy $(SolutionDir)file.xml $(ProjectDir)$(OutDir)file.xml

You 1 may also need this to add to your path:

Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
Score: 5

I use a helper class to deal with getting 21 basic paths I might want to access in my 20 Unit Tests.

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

Sometimes my interactions with 19 paths are more complex; I often use a central 18 class I name "App" to indicate 17 some basic details about the application, like 16 its root folder, its root namespace and 15 module, etc. Classes will sometimes depend 14 on App's existence, and so instead I'll 13 place an init method on App that uses code 12 like the above to initialize itself for 11 test harnesses, and call that method from 10 the Init command in a Unit Test.

(Updated)

Old Answer

I 9 found this helps for getting arbitrary paths 8 to access files in the project folder you 7 intend to test (as opposed to files in the 6 Test project folder, which can make busywork 5 if you need to copy things over).

DirectoryInfo projectDir = new DirectoryInfo(@"..\..\..\ProjectName");
string projectDirPath = projectDir.FullName;

You can 4 then use either of those variables to access 3 whatever you need from the related project. Obviously 2 swap "ProjectName" out for the 1 actual name of your project.

Score: 1

Resources are just resources and that's 8 it, no need to complicate. If you don't 7 want to embed them then you could add these 6 files as "Content" resources to your project 5 and set them to Copy always. Then specify the sub-folder 4 in your code:

var xmlDoc = XElement.Load("ProjectSubFolder\\Resource.xml");

This will automatically load 3 the resources from the project output (running 2 assembly location) bin\$(Configuration)\ResourceSubfolder\

This works for all types 1 of projects, not just unit tests.

Score: 0

I would just put the path in the app.config 11 and load from the default path. In my team, i 10 am really anal about developers changing 9 paths, so i make all my developers have 8 the same exact paths and files on their 7 computers, so i dont have an issue of any 6 rogue developer changing a path to suite 5 his workspace.

For example , all developers 4 in my team must use C:\Project\Product\Module, etc 3 etc. I also make sure all their software 2 installed also is standard. This way, i 1 can ghost any machine into any other easily.

Score: 0

I think in VS.NET 2012 DeploymentItem attribute 1 works without any Test Settings configuration.

More Related questions