In MsTest if I need some file from another project for my test, I can specify DeploymentItem attribute. Is there anything similar in NUnit?
I've done a few improvements to Alexander Pasha's solution: I've given the attribute the same signature as the MSTest one, such that the first parameter is the absolute or relative file or folder to deploy, and the optional second parameter is the absolute or relative path to which it is to be deployed. In both cases 'relative' means to the executing program. Also I've removed any read-only attribute from the deployed file. This is important - if a previously deployed file can't be overwritten the attribute will throw. It is also worth noting that MSTest and NUnit have very different strategies when it comes to deploying the files that are to be used during testing. MSTest may or may not copy files to a deployment folder - see here. NUnit uses the ShadowCopyFiles property of the AppDomain, which deploys to a very obscure location in the user's temp folder. While shadow copying can be turned on and off in NUnit itself, I don't know how to manipulate it when using Test Explorer in Visual Studio. In this regard it is important to note that the Visual Studio NUnit Test Adapter prior to Version 2 has shadow copying turned on but in version 2 onwards it is turned off. This can have a major impact on tests that use deployment items and is well worth being aware of. Here is my version of the DeploymentItemAttribute:-
namespace NUnitDeploymentItem
{
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true, Inherited = false)]
public class DeploymentItemAttribute : Attribute
{
///
/// NUnit replacement for Microsoft.VisualStudio.TestTools.UnitTesting.DeploymentItemAttribute
/// Marks an item to be relevant for a unit-test and copies it to deployment-directory for this unit-test.
///
/// The relative or absolute path to the file or directory to deploy. The path is relative to the build output directory.
/// The path of the directory to which the items are to be copied. It can be either absolute or relative to the deployment directory.
public DeploymentItemAttribute(string path, string outputDirectory = null)
{
// Escape input-path to correct back-slashes for Windows
string filePath = path.Replace("/", "\\");
// Look up where we are right now
DirectoryInfo environmentDir = new DirectoryInfo(Environment.CurrentDirectory);
// Get the full path and name of the deployment item
string itemPath = new Uri(Path.Combine(environmentDir.FullName, filePath)).LocalPath;
string itemName = Path.GetFileName(itemPath);
// Get the target-path where to copy the deployment item to
string binFolderPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
// NUnit uses an obscure ShadowCopyCache directory which can be hard to find, so let's output it so the poor developer can get at it more easily
Debug.WriteLine("DeploymentItem: Copying " + itemPath + " to " + binFolderPath);
// Assemble the target path
string itemPathInBin;
if (string.IsNullOrEmpty(outputDirectory))
{
itemPathInBin = new Uri(Path.Combine(binFolderPath, itemName)).LocalPath;
}
else if (!string.IsNullOrEmpty(Path.GetPathRoot(outputDirectory)))
{
itemPathInBin = new Uri(Path.Combine(outputDirectory, itemName)).LocalPath;
}
else
{
itemPathInBin = new Uri(Path.Combine(binFolderPath, outputDirectory, itemName)).LocalPath;
}
// Decide whether it's a file or a folder
if (File.Exists(itemPath)) // It's a file
{
// Assemble the parent folder path (because the item might be in multiple sub-folders.
string parentFolderPathInBin = new DirectoryInfo(itemPathInBin).Parent.FullName;
// If the target directory does not exist, create it
if (!Directory.Exists(parentFolderPathInBin))
{
Directory.CreateDirectory(parentFolderPathInBin);
}
// copy source-file to the destination
File.Copy(itemPath, itemPathInBin, true);
// We must allow the destination file to be deletable
FileAttributes fileAttributes = File.GetAttributes(itemPathInBin);
if ((fileAttributes & FileAttributes.ReadOnly) != 0)
{
File.SetAttributes(itemPathInBin, fileAttributes & ~FileAttributes.ReadOnly);
}
}
else if (Directory.Exists(itemPath)) // It's a folder
{
// If it already exists, remove it
if (Directory.Exists(itemPathInBin))
{
Directory.Delete(itemPathInBin, true);
}
// Create target directory
Directory.CreateDirectory(itemPathInBin);
// Now Create all of the sub-directories
foreach (string dirPath in Directory.GetDirectories(itemPath, "*", SearchOption.AllDirectories))
{
Directory.CreateDirectory(dirPath.Replace(itemPath, itemPathInBin));
}
//Copy all the files & Replace any files with the same name
foreach (string sourcePath in Directory.GetFiles(itemPath, "*.*", SearchOption.AllDirectories))
{
string destinationPath = sourcePath.Replace(itemPath, itemPathInBin);
File.Copy(sourcePath, destinationPath, true);
// We must allow the destination file to be deletable
FileAttributes fileAttributes = File.GetAttributes(destinationPath);
if ((fileAttributes & FileAttributes.ReadOnly) != 0)
{
File.SetAttributes(destinationPath, fileAttributes & ~FileAttributes.ReadOnly);
}
}
}
else
{
Debug.WriteLine("Warning: Deployment item does not exist - \"" + itemPath + "\"");
}
}
}
}