Share via


Test Automation Foibles: Hard coded paths

Anyone who has listened to me talk about automated test design knows that I loathe hard-coded strings in test automation. Yes, I know that static test data is important, but it is almost never a good practice to hard-code strings or other test data in the body of your test code (or any code for that matter). 

But, as I started porting some of my demos to run on Windows Vista I realized that I violated my own axiom by hard-coding local paths for test artifacts (test files) in my own test code. Granted this code was for demonstration and training, but that is not an excuse for slovenly written code. Besides, as a general principle we should develop all code following which ever best practices you adhere to because we never really know who is going to critique that code or use it as an example elsewhere. 

Unfortunately, I am not alone in committing this mistake and I occasionally encounter hard coded paths in various automated test projects. Perhaps this occurs because it takes less effort (and lines of code) to hard code a path rather than get the path using a .NET method or Win32 API, or perhaps because we might assume the code will never run on a different machine (both of which are probably bad assumptions). No matter what the reason hard-coded paths are generally not a good practice.

In some automated tests I generate dynamic test data during runtime and create a file to temporarily store that data for use in the test, or save other user files with information that doesn't necessarily have to persist after the completion of that automated test. (In generating dynamic test data I only have to log or record the seed value used to generate the data.) In one demonstration I created test artifacts (test files) and saved them to the root of the C: drive. (Yes, I know the old PC-98 architecture used in Japan might not have a C: drive because it had a floating drive architecture, but on the PC/AT architecture running the Windows OS environment the default drive is almost always C:.)  Writing to the root directory of the C:\ drive was easy and relatively safe in strictly controlled environments, but it is certainly not the best thing to do (and generally bad from a security perspective). But, fast forward to Windows Vista and my code breaks. Even though I have administrator privileges when I run the demo code and attempt to save a file to the root of C:\ on the Vista platform the system gives me an error message indicating I don't have permission to save in that location. Unexpected dialog == unexpected behavior == code breaking. File not found by the test oracle in the expected location == false positive. Demonstration falling apart in front of an audience == embarrassment (because it really does no good to say "well, it worked on my other machine!").

Avoiding hard-coded paths for storing temporary test artifacts (e.g. disposable test files generated during the automated test) in automated test cases is easy with C# and the .NET framework. If we need the path to the desktop folder, or program files folder (or other special folders created by the Windows operating system) the GetFolderPath method in the System.Environment class gets the path to "special" system folders. The special folders include folders such as the system folder \windows\system32), the Program Files folder, the Desktop folder, the MyDocuments folder, etc. and are listed on MSDN under the Environment.SpecialFolder enumeration.)

For example, the following snippet returns a path to the current user's Documents folder ("C:\Users\[logged in account name]\Documents") which is a good place to store temporary test artifacts.

             string desktopFolderPath = Environment.GetFolderPath(
                Environment.SpecialFolder.MyDocuments);

It would probably be better to use a StringBuilder object as illustrated in the following example because a string is an immutable object in C#, and we will probably want to append the path separator and eventually a filename for the test artifact.

             StringBuilder desktopFolderPath = new StringBuilder(
                Environment.GetFolderPath(
                Environment.SpecialFolder.MyDocuments) +
                Path.DirectorySeparatorChar);

This returns a StringBuilder object of "c:\\users\\[logged in account name]\\desktop\\".

Another useful location to temporarily store disposable test artifacts might be the current user's temporary directory ("C:\\Users\\[logged in account name]\\AppData\\Local\\Temp\\") as illustrated in the following example:

             StringBuilder tempFolderPath = new StringBuilder(
                Path.GetTempPath());

Using the Environment.SpecialFolder enumeration or the .GetTempPath method are easy ways to get the path to a folder to store disposable test artifacts on the local machine without hard-coding a path in the automation code. It is likely this will be reused, so it is a good idea to wrap some methods for inclusion in your test automation framework or library. Also, don't forget to delete or move any test artifacts from the test machine after the automated test completes. It is generally a best practice to restore a system to its' pre-test state after your automated test executes.