Reputation: 501
I have a windows form application that is working without errors (compilation creates .exe in bin\debug along with a folder called 'Images'. This 'Images' folder is in my project solution folder and is set to "always copy".
When the code is compiled, all is well and there are no System.IO exceptions.
However, if that class that refers to the images is instantiated without compiling and through a unit test harness, I see the following:
System.Drawing.Image.FromFile(String filename, Boolean useEmbeddedColorManagement) at System.Drawing.Image.FromFile(String filename) at YahtzeeApplication.GameBoard..ctor() in E:\workspaces\visual studio projects\Yahtzee\YahtzeeApplication\YahtzeeApplication\GameBoard.cs:line 124 at UnitTestProject.GameBoardTest.GameBoardElements() in E:\workspaces\visual studio projects\Yahtzee\YahtzeeApplication\UnitTestProject\GameBoardTest.cs:line 37 Result Message: System.IO.FileNotFoundException : Images\1.dice.GIF
Here is the code that loads the image:
diceImageArray[0] = Image.FromFile("Images\\1.dice.GIF");
I was seeing if the test class or the instantiated class was not seeing the images. but when I put a folder called 'Images' in either location relative to call the error didn't go away.
What do you do for this scenario in Unit testing?
Upvotes: 0
Views: 243
Reputation: 13736
The relative path is incorrect because you have no control over the current directory, which is what the relative path is based on. The same code would also fail, if you simply ran a console application without first changing into the directory that contains the image directory, for example...
foo\bar\myprogram.exe
In general, the user of a program has control over the current directory. It's bad form for a program to change the current directory or to rely on it being set to any specific location... like the location of the assembly being run.
Alternative ways of locating the image directory depend on whether the path is determined in your test or in the application under test. If it's in the test, then NUnit has TestContext.TestDirectory
, which is the path to the directory containing the test assembly. If it's in the application itself, then the application needs to be coded in a way to find the images directory relative to some specific location, like the directory containing the main program. If you indicate where this code is located, then I can give a more exact suggestion.
Update - 22-Jan-2019
The use of a relative path within your application is a weakness of the application, which will cause it to fail in certain circumstances unless you have complete control over the current directory setting whenever the program is run. Running the tests under NUnit is just one such circumstance. IMO, you should change the application so that it finds the images at a path relative to the directory containing the exe and not relative to the current directory. This takes a little more code but is better because it's actually what you intend to happen. Your tests are doing you a favor by pointing out this problem!
Here's some code that will locate images (see exception below) relative to the location of assembly that does the loading of the images...
string assemblyPath = GetType().Assembly.Location;
string assemblyDir = Path.GetDirectory(assemblyPath);
string imagePath = path.Combine(assemblyDir, "Images\\1.dice.GIF");
diceImageArray[0] = Image.FromFile(imagePath);
I spread the code over multiple lines so you can more easily see each step. You can, of course, combine some of them. The code has only been "compiled" in SO, so I'll leave any errors for you to fix. :-)
The exception to the above code is if your code is being shadow-copied. Then you need access to the original location it came from and not the current location. If that happens to be the case, it needs a little more code and I didn't want to overly complicate the example.
If the assembly that loads the images always locates them relative to itself, then your tests should work so long as you make sure the images exist at that location.
Upvotes: 1