This is more for my own reference but has proved rather useful. The problem it solves for me is that when automated Selenium tests run and fail its usually quite a task to figure out what went wrong. The best way around this is to take a screen shot of the issue. However taking a screen shot can end up with a folder on a tester server full of images you have to look through to find your test result image. The best option is to attach a screen shot your test takes when it fails to the results of the currently running test.

Below is how to do this with MSTest running in VSTS. All of our Selenium tests run as part of a timed VSTS Release Hub release twice a day.

1 [TestMethod] 2 public void BurnUp_86_CheckIterationPathsLoad() 3 { 4 bool isLoaded = false; 5 6 try 7 { 8 _selenium.ShowSelectedData(); 9 10 _selenium.ClickIterationPath(); 11 isLoaded = _selenium.CheckIterationPathsLoad(); 12 } 13 catch (Exception) 14 { 15 16 var testFilePath = _selenium.ScreenGrab("BurnUp_86_CheckIterationPathsLoadERROR"); 17 18 AttachScreenShotFileToTestResult(testFilePath); 19 20 throw; 21 } 22 23 Assert.IsTrue(isLoaded); 24 } 25 26 public TestContext TestContext { get; set; } 27 28 public void AttachScreenShotFileToTestResult(string screenShotPath) 29 { 30 try 31 { 32 if (!string.IsNullOrEmpty(screenShotPath)) 33 { 34 TestContext.AddResultFile(screenShotPath); 35 } 36 } 37 catch (Exception) 38 { 39 40 //We don't want to stop the tests because we can't attach a file so we let it go....let it go.. let it go... 41 } 42 43 }

Lets take a moment to step through the test method above called BurnUp_86_CheckIterationPathsLoad(). The test is contained in a try catch. All of my selenium functionality I keep inside a separate class so it abstracted and encapsulated from the actual unit tests, this helps greatly with maintaining my test as I only need to focus on the Selenium classes if the page layout for example changes. As part of this class it has a base class where I keep functionality common to all tests such as the ScreenGrab function found inside _selenium (more on this later).

If my test fails my try catch will catch the exception this is where I will take a screen grab of the issue and then allow the original exception to bubble up. But after I have taken a screen grab I attach this to the the current running tests results using the AttachScreenShotFileToTestResult function. You can see inside this function, I don’t care if it fails to attach the screen shot to the test results, I’d rather the rests of the tests continue to run. (I can almost sense the shock from my fellow developers Smile). The key piece of functionality to take away here is TestContext.AddResultFile. This is given the path to where we saved our screen grab in the previous step.

So what about that screen grab functionality?

Selenium has had the ability to take screen shots for a while. Below is the function in my _selenium class that takes the screen shot using the current version of the IWebDriver.

1 public class SeleniumBase 2 { 3 protected IWebDriver driver; 4 5 public string ScreenGrab(string test) 6 { 7 string baseDirectory = "C:\\UITests"; 8 string screenGrabs = Path.Combine(baseDirectory, $"{DateTime.Now:yyyy-MM-dd}"); 9 10 if (!Directory.Exists(baseDirectory)) 11 { 12 Directory.CreateDirectory(baseDirectory); 13 } 14 15 if (!Directory.Exists(screenGrabs)) 16 { 17 Directory.CreateDirectory(screenGrabs); 18 } 19 20 21 //Create these folders if not present 22 string filename = Path.Combine(screenGrabs, $"{test}-{DateTime.Now:yyyy-MM-dd_hh-mm-ss-tt}.png"); 23 24 try 25 { 26 Screenshot ss = ((ITakesScreenshot)driver).GetScreenshot(); 27 ss.SaveAsFile(filename, System.Drawing.Imaging.ImageFormat.Png); 28 29 30 } 31 catch (Exception) 32 { 33 34 //We swallow the exception because we want the tests to coninue anyway. Taking a screen shot was just a nice to have. 35 return string.Empty; 36 } 37 38 39 return filename; 40 } 41 }

So what does the result look like?

Below are the results from one of our automatic test runs that are run for us by Visual Studio Team Services Release Hub. If I click on the test that has failed you can see in the results section an attachment has been added which is the screen grab we took when the test failed.


Got a better way of doing the above? Or would like to recommend some changes? Don’t be shy leave a comment, I’d love to hear from you Smile