xUnit.Net is not using app.manifest for longPathAware - c#

I am using xUnit.Net for my Unit- and Integrationtests in C#. In some tests I need to copy files or create directories. In some cases I have paths longer than MAX_PATH which is 260 characters long. To work with these paths I enabled long paths in windows as descriped here.
This is working fine for a console application, but not for my xUnit tests. I guess xUnit is not loading the app.manifest file because there is no .exe file. I am not sure if it is a problem with xUnit or a general problem.
Does anyone know if there is a solution for this problem? I know I could use \\?\ as prefix to make it work but that is not really an option because of the code changes.

Related

Unit Testing, Current Directory and Application Path

When coding parts of an application that require access to a directory, I often write the code so that if the Directory is specified using a relative path, the system assumes that the intent is to use a directory subordinate to the directory/folder that the Application (Executable) is running in (or was loaded from).
But when I run Unit Tests which exercise this code, it turns out that the Application path is a completely different directory, because the "Application " is the Test runner Harness, and it is running in a separate directory.
For writes this is no problem, but if the code is attempting to read a file configured in the solution as [Content] from a directory that the compiler copied as part of the build process, this file is of course not in the Test Runner version of the folder at all.
This can be resolved for files that are physically in the test project solution space, (by adding additional instructions on TestRunner configuration), but as far as I know, if the file is specified in the Solution as a link to a physical file located outside the project space, then I have yet to be able to find a simple solution to the problem.
What solutions to this issue exist? and what are the pros/cons of each one?

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 to deploy files to the test folder

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?

Why my WPF program cannot run without Visual Studio?

I made a WPF program which uses SQLite. And by using Visual Studio 2012, it generates both Debug and Release version exe file. When I go to Debug or Release directory and run my exe file, e.g. MultiStart.exe, it can run normally.
But if I copy the MultiStart.exe to my Desktop and try to run it, it failed.
By several tests, I found that I also need to copy files MultiStart.exe.config and System.Data.SQLite.dll to my Desktop. And then it can run now.
But why? Do we have better solution so that I can make it run without addition files?
Thanks!
Why my WPF program cannot run without Visual Studio?
The question title is not really accurate since it's not really related Visual Studio. MultiStart.exe is dependent on configuration (MultiStart.exe.config) as well as other assemblies (System.Data.SQLite.dll). Without these dependencies the application cannot run (because that is how .NET works).
WPF doesn't necessarily need a config file to run so the question is what is in your config file that the application needs. It might be possible to move this configuration information into the code (e.g. connection string) and remove the app.config but then the values will be hard coded in the application.
In terms of dependent assemblies, instead of deploying them it is possible to embed them as resources and then use the AppDomain.AssemblyResolve Event to read the assembly from a resource (see Embedding assemblies inside another assembly for an example).
Another approach instead of embedding assemblies as resources is to merge them into one assembly. ILMerge is a popular choice for merging assemblies but I read that it can have issues with WPF assemblies (not sure if that applies to you). See Merging dlls into a single .exe with wpf for some other ideas for merging assemblies with WPF.
Note that setting PATH variables does not work because .NET does not use the PATH for resolving assemblies -- see How the Runtime Locates Assemblies for the details.
Another, option instead of copying the MultiStart.exe to the desktop is to use a shortcut on the desktop that links to the appropriate directory. Perhaps that is a simpler solution
You can also use ILMerge to merge all dependencies into single .exe file to simplify distributiuon of your application.
More detaiils on ILMerge can be found here: ILMerge on CodeProject
Example of usage: ilmerge /target:winexe /out:YourDestinationApp.exe
YourCurrentProgram.exe System.Data.SQLite.dll
Better solution that i used to do with my windows form apps is, Copy the entire folder, which contains supporting files. place it where you want. then create a shortcut of your .exe on your desktop. That always worked for me.
Because you are missing some dependency. You can open your config file and set the dependency...but I wouldn't recommend you to change config file manually.
You can also copy the dependent dll in system32 folder. ..but its only a trick because exe first search dlls in current folder than system 32 folder.
Because you're missing things from your PATH. Visual Studio is probably set to copy DLLs to the target directory on build.
You're almost certainly pulling in external libraries. Some of these are part of .NET, while others are packaged in libraries in specific folders. When you start your exe, it looks in your PATH and the current folder for everything (which includes all DLLs Visual Studio copied).
When you moved the exe to the desktop, suddenly it had no idea where those DLLs are. You haven't specifically added them to your PATH, and they are no longer in the current folder. This is why copying those DLLs to your desktop magically made them work.
Unless you stop use SQLite, there is not a way for you to not need that DLL (there are lots of ways to package/reference it though).

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.

Categories

Resources