How to deploy files to the test folder - c#

I am writing a test project to test the e-mail functionality. This functionality opens an HTML file that contains the message template for the e-mail. When I try to run I get an error which reports that the template file could not be found. I have figured out that when running the test, the dll's etc. are copied to a different location which looks like:
C:\Users\Cornelis\AppData\Local\Temp\TestResults\Cornelis_CORNELISDESKTOP 2014-07-13 18_07_47\Out\
I searched around on the internet and find some partial solutions but none helped me completely to solve my problem. What I have found so far is:
If I go to the properties of the file in my solution explorer, I set the value of the property 'Copy to output directory' to 'copy always'.
I added the DeploymentItemAttribute to my test method. This caused my file to be copied into the debug folder of my unit test, but not to the folder mentioned earlier.
I also found a lot of solution involving a *.testsettings where I had to turn on an option Enable Deployment. But if I add such a file to my solution, I get an error which says no tests could be found. And according to Microsoft I shouldn't use such settings file for what I want to reach:
Caution
Unit tests run more slowly if you use a test settings file. We
recommend that you do not use a test settings file with unit tests.
You can configure unit tests by using the .runsettings file instead.
To deploy additional files, use DeploymentItemAttribute.
http://msdn.microsoft.com/en-us/library/ee256991.aspx
What am I doing wrong here? What do I need to do so my test can find the template file I require?

Related

Unable to run unit tests in the Bin Folder c#

Background: I have a consuming a 3rd party class library which uses typeof(myClassFactory).Assembly.Location
to determine its location and then uses this to load another dll. This is breaking because the second dll is not copied to the temporary location. Therefore I want to make the unit tests run from within the /bin folder.
I'm using Vs2017 pro with xUnit and tried the VS test runner and resharper and both behave the same.
What I've tried so far: I've tried creating a test.runsettings file and setting the following:
<DeploymentEnabled>false</DeploymentEnabled>
as suggest here How to make unit test run in bin folder
however the code is still executing in c:/users/myuserName/Local/Temp/{someGuid}/{someguid}/....etc
Question: How do i make it run in the /bin directory?
I found my issue, it was to do with xUnit not using the .runsettings file.
To fix this, I added a new file called xunit.runner.json and added the following code:
{
"shadowCopy": false
}
I added this to the root of the solution and then set it to be copied to the output by right clicking on the file:
Properties > Copy to Output Directory
set to 'Copy if newer'
This made it work

Copying static files from a referenced project to the test deployment directory for unit tests

I'm trying to configure Visual Studio's in-built test runner (msunit) to copy some static files to the output directory, but am so far unsuccessful.
The static files reside in a common test project which all the other test projects reference. The static files have
Build Action: Content
Copy to Output Directory: Copy always
When each test project is built, the static files are copied to the \bin\Debug\ directory, but when the tests run and msunit copies everything to a \TestResults\ directory, these static files are not copied.
Copying the files to the output directory
According to this MSDN page,
To make additional files available during a test, such as test data or
configuration files, incorporate the files into your project and set
the Copy to Output property. If that is not practical, deploy
additional files or directories by using the DeploymentItemAttribute
on test classes or methods.
Taking these two suggestions in turn, the first I've tried without success... or must the static files be in each of the test projects? Is not enough to have them in a referenced project?
And as for the DeploymentItemAttribute, I really don't want to have to put this above every test class in every test project.
Running the tests in their original location
Another option would be to run the tests in their original location rather than deployed to the \TestResults\ directory, which I'd be happy to do if I could figure out how to configure such.
This MSDN page explains how to configure how the tests are run, though despite being the only page where the *.runsettings file is described, it's woefully short on detail. For example, it provides a sample wherein the <TestAdaptersPaths> element contains a dummy value, but doesn't explain what it can be replaced with.
And this *.runsettings file also doesn't explain if it's even possible to run the tests in the original output directory. This is something which is possible with the older *.testsettings file, but the documentation also says that a *.testsettings file may only be used in legacy mode, which is slow and not as robust; and although I may specify a *.testsettings file in the *.runsettings file, I would also then have to force the tests to run in legacy mode.
So it appears to be the case that the older version permitted a configuration setting which indicated that the tests should not be deployed to another directory, but that the new version doesn't support this (or doesn't document that it supports it).
Using xcopy
Here is another MSDN page wherein it is suggested to define a post-build task to xcopy the files into place. I've tried this as well and the files never appear in the deployment directory.
So in summary, everything I've tried has proven unsatisfactory. Could someone please explain how I can tell my test projects to copy static files from a referenced project into the deployment output directory (preferable), or how I can configure the tests to run in their original location?
Update
I'll also add that if an individual test method is run, the test will run in the standard output directory (that specified in the project's properties, default is "bin\Debug\"). In such a case the test runs as expected because the static files are present in the standard output directory; if multiple tests are run (either choosing "Run all tests" at project or class level) then the tests are run from a uniquely-named deployment directory under the "TestResults\". It is in this latter case where the static files are not copied.
Furthermore, if I decorate a test class with [DeploymentItem("...", "...")] then the specified file is copied, but if I decorate a common class (used for DB setup) with the same attribute (and which is also decorated with [TestClass]) then the specified file is not copied.

How do I get a Unit Test to copy my DLLs and other files when I run a test?

I'm working on an application and I have created a number of unit tests for it. The project with the test class depends upon 3 third party DLLs. When I go to the bin\Debug folder for the test project, the Dlls are there. But when I run the test, the DLLs are not being copied into the TestResult\\Out folder.
There is also a log4net.config file from another project that I would like to have copied. This one is not showing up in the test project's bin\Debug folder, so that's another issue I have to fix.
How do I get these files to copy when I run the unit test?
Tony
You can use a DeploymentItemAttribute to copy files to the bin (or other) directory.
[TestMethod()]
[DeploymentItem("log4net.config")]
public void SomeTest()
{
...
}
We have a bin folder containing 3rd-party DLL's that have to be part of builds. They are flagged with the 'copy local' attribute in the reference.
As for individual files, you can do the same - Set 'Copy to output directory' to true.
I have found if your tests are being deployed to the test area (true by default), copy local won't work in some circumstances such as dynamic assembly loading.
You can either turn this deployment off by using a runsettings file (https://msdn.microsoft.com/en-us/library/ms182475.aspx) and
<DeploymentEnabled>False</DeploymentEnabled>
Or, a small hack (slightly ugly as it requires manual/hard coding the assembly), by using a DeploymentItem for the binary (mentioned in other answers, but, not specific to handling dlls as per the OP):
[DeploymentItem("bin\\release\\iRock.dll")]
[DeploymentItem("bin\\debug\\iRock.dll")]
Recommend doing both debug/release, depending on what is used on your CI/Dev.
Such dll copying ( apart from referencing them - where you can say Copy Local) and putting them in the out folder should not be part of your tests, but part of your build / packaging process. Have build scripts which do the necessary copying of the dlls.
When you debug from studio, use Deployment attribute on class or testmethod to copy the required DLLs and config files to the Out folder from where MSTests are run. If you run from command line, use a TestSettings file and disable the Deployment option and set your BIN folder as the working directory. Use/refer this TestSettings file in your command line for running mstest. This way, you can run mstest right in your BIN folder without dumping the DLLs into a out directory. Again, use deployment attribute to debug from studio, there testsettings will not work.

TFS, testing and placement of test files (where)

I am currently experimenting with TFS, and I really like it.
One small question, regarding test files:
I have a directory with some demo TXT, images, dirs... These are used during tests, so up until now, the path was hardcoded to a folder on my computer. Now I need to change this, of course, the TFS need access to the files too.
My idea was to place them inside the folder of my solution, I currently have roughly this structure:
Solution Folder
mysol.sln
SomeProjectDir
OtherProjectDir
_LIB for external .dll
_DEMO_FILES for test files
The whole solution folder is under source control. Would you do it the same way? How is the best and elegant way to get the "real" path of the folder for usage in unit tests? Using the execution path an cutting away the rest? Do test files belong under source control?
Thanks for any input,
Chris
EDIT: Beside the tip given in the answer, please be aware that with testing there are some pitfalls with this. The test is executed in a different folder (often named after some timecode), the testfiles do not get copied there automatically. Even if they are set to copy always.
The solution is to either add the files manually by using a attribute called DeploymentItem in the unit-test, or, in my opinion much better, adjust the Local.testsettings and add the folder there. Keep in mind, the folder itself will not be added, so you need to do it one level higher..
You will understand what I mean if you try it. Or search for DeploymentItem on google
test files are part of your project, so there is NO reason to keep them out of the version control system. You should commit to the version control system everything that is needed to build, test and run your system, including 3rd party libraries, config files, test files, and even arguably documentation. Please note that most of these things should be part of your Visual Studio solution as well.
In my projects usually I try to have all my resources as Embedded Resource, so that I don't need to figure out the path, they are compiled into the assembly. If for some reasons I can't go this way, I would make the build copy them to the output folder (so mark them as copy always in VS) and then use relative paths.

How can I get "Copy to Output Directory" to work with Unit Tests?

When I build a unit test project before the tests are executed the test output is copied to a TestResults folder and then the tests are executed. The issue I'm having is that not all the files in the Debug/bin directory are copied to the TestResults project.
How can I get a file that is copied to the Debug/bin directory to also be copied to the TestResults folder?
The standard way to do this is by specifying the deployment items in the .testrunconfig file, which can be accessed via the Edit Test Run Configurations item in the Visual Studio Test menu or in the Solution Items folder.
You can specify deployment attribute like an example shown below; Also you need to set "Content" & "Copy if newer" property ( there is no documentation on the later settings, but you have set those to make it work.
[TestMethod]
[DeploymentItem("mytestdata.xml")]
public void UploadTest()
{
}
I had to turn on "Enable Deployment" under Test -> Edit Test Settings -> Local -> Deployment for the [DeploymentItem] attribute to work.
All three answers are correct, depending on your needs.
Adding files to deploy in the .testrunconfig (.testsettings in VS2010) will copy all of those files to every test output folder, even for unrelated tests run in isolation. If you run one test, all the test data files listed in the deployment section of .testssettings will be copied to the test output folder.
In my tests I need to copy an expected XML file to the test output folder to compare with the actual test output XML. I use the DeploymentItem attribute to only copy the XML file related to the test(s) being run. In VS2010 I had to enable deployment in the .testsettings file (but not add any paths) and then reference the XML file path relative to the TestProject in the DeploymentItem.
Hope this helps.
I had a similar problem but mine had to do with pointing to the TraceAndTestImpact.testsettings file instead of the Local.testsettings file. You can change from one to the other under the Test/Select Active Test Settings menu.
The following works in VS2012 for test projects included in multiple solutions without using a testsettings file:
1) Arrange the files and folders you wish to deploy into a folder in the test project directory.
2) In the project properties, create a post build step
xcopy /Y /S /i "$(ProjectDir)<Project_Folder_Name>\*" "$(TargetDir)<Deployment_Folder_Name>"
$(ProjectDir) and $(TargetDir) are macros that will be interpreted by VS and should be included as such.
<Project_Folder_Name> is the name of the folder created in step 1.
<Deployment_Folder_Name> is the name of the folder in which the test files will be deployed and should be named so that it will be unique when multiple test projects are deployed to the same directory, e.g. <Project_Name>_TestInputs.
Test files in shared locations should also be copied to the target directory deployment folder to limit test interactions. Provide the source path relative to the $(ProjectDir) macro. For example "$(ProjectDir)..\..\Common Files\C1219TDL-2008.xml".
3) Add a [DeploymentItem(source, destination)] property to either each test method that uses a deployment file (best practice) or to the test class (easier practice for the lazy or hurried, and the easiest way to update a project the previously used relative paths or a testsettings file).
On a test method, source is the path to the file or directory used in the test method relative to the target directory as created by the xcopy and destination is the path to the directory in which it will be created relative to the deployment directory. So that tests run consistent in either the target directory or a deployment directory. The destination path should be the same as the source path without a file reference. Example: [DeploymentItem("Example_TestInputs\C1219TDL-2008.xml","Example_TestInputs")]. The DeploymentItem should be included on every method that uses that file or directory.
On a class, source and destination are both the name of the folder created in the target directory by the xcopy; this will copy the entire folder to the deployment directory when any test in the class is run. Example: [DeploymentItem("Example_TestInputs","Example_TestInputs")]
4) In the test methods, you can now access files and directories with confidence they will be in the working directory regardless of where Visual Studio has decided to put it that day, e.g. File.Exists(".\Example_TestInputs\C1219TDL-2008.xml").
Would like to just enhance the accepted answer by mentioning a way to get it to deploy specifically for dll's rather then the normal method of using it for data or config etc, for the circumstances where CopyLocal doesn't work:
[DeploymentItem("bin\\release\\iRock.dll")]
[DeploymentItem("bin\\debug\\iRock.dll")]
[TestMethod]
[DeploymentItem("ProjectName/Folder/SubFolder/file.xml", "Folder/Subfolder")]
public void YourTestMethod()
{
// in the method you are testing you should have this:
var filePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase) + "/Folder/Subfolder/file.xml";
}
Try out the Post-Build event command line from within Visual Studio (if you are using that IDE).
In Visual Studio 2012 you don't need a DeploymentItem attribute for the simple case. See my answer here
The accepted answer is correct and so are most of the other answers. However, over the years I have found that the Deploment system of Visual Studio Unit Tests using DeploymentAttribtue and Copy to Output to be cumbersome if you have a large number of data files. I have found that keeping the files in their original location worked better.
Full details in my other answer here.
https://stackoverflow.com/a/53004985/2989655
Hope this helps.

Categories

Resources