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?
Related
Is it possible to attach a flat file to windows-service?
My windows-service uses few flat file (for data purposes). Usually, if it's a normal executable I would place those files in the same directory as exe. How can I achieve that with windows-service?
I've done some research on this, but all I found was:
1. Pass a path to those files as a parameter to windows-service.
2. Make a fixed path and just require those files there
But I don't like those solutions. I was wondering if it's possible to attach those files to the windows service while installing it?
How about adding these files inside the project as Embedded Resources? They won't show up on the disk, but you could still properly read them from inside the assembly itself.
Here's some reference: https://support.microsoft.com/en-ie/kb/319292
You can look up the directory that your application is installed in at runtime, using the Application.StartupPath property from System.Windows.Forms. This works for both applications and services. You should avoid hard-coding the path that you think your application is installed in, because the end user may have installed it somewhere else. You should also avoid using the current directory (i.e., opening the file by name only, without a specific path) because the user may be running your application with a different current directory.
Note that installutil does not make a copy of your service executable. So the service runs from the same directory that it was in when you installed it, and any files you place in that directory should still be there when the service is running.
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.
I have a program that is stored in program files folder.
I created windows service to run it, but when I do, it doesn't start.
I used process monitor to see what happens, and realized that it's looking for all dependencies in system32 folder.
If I take the program, with all referenced dependencies and paste them into the root of system32 folder, it works! But I don't like it that way, I want to run it from specific folder.
Add your program's folder to PATH environment variable and your service will find it there...
The PATH trick didn't work. It gave me error about some depended file software were trying to locate. But I found the solution. You can provide working directory:
process.StartInfo.WorkingDirectory
That did the trick. Thanks anyway!
I have found that DeploymentItem
[TestClass(), DeploymentItem(#"TestData\")]
is not copying my test data files to the same location when tests are built and run on different machines.
The test data files are copied to the "bin\debug" directory in the test project on my machine, but on my friend's machine they are copied to "TestResults\name_machine YY-MM-DD HH_MM_SS\Out".
The bin\debug directory on my machine can be obtained with the code:
string appDirectory =
Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
and the same code will return TestResults\*name_machine YY-MM-DD HH_MM_SS*\Out on my friends PC.
This however isn't really the problem. The problem is that the test data files I have made have a folder structure, and this folder structure is only maintained on my machine when copied to bin\debug, whereas on my friends machine only the files are added to the TestResults\*name_machine YY-MM-DD HH_MM_SS*\Out directory. This means that tests will pass on my machine and fail on his!
Is there a way to ensure that DeploymentItem always copys to the bin\debug folder? Or a way to ensure that the folder structure will be retained when DeploymentItem copies the files to the TestResults\*name_machine YY-MM-DD HH_MM_SS*\Out folder?
After playing around for a while, it looks like the best way to deal with it is to ensure that for every subdirectory, you add a new DeploymentItem making sure that you specify the "outputDirectory", like so:
[TestClass(), DeploymentItem("TestData\\", "TestData"),
DeploymentItem(#"TestData\\SubDir\\", "TestData\\SubDir")]
This allows the tests to run on your machine - hope this helps someone!
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.