It's far from perfect (as you would have to reference it per test class and the file doesn't really get attached) but this is what I did.
- Created a base class for all tests to handle global cleanup logic
- Added a public TestContext property
- Implemented [TestCleanup] method
- Compared test result and saved screenshot
- Used the AddResultFile to add the file path to the test report
Test class
[TestClass]
public class FailingTest : TestsBase
{
[TestMethod]
public void Failing()
{
throw new Exception("Fail");
}
}
Base class
[TestClass]
public abstract class TestsBase
{
public TestContext TestContext { get; set; }
[TestCleanup]
public void SaveScreenshotOnFailure()
{
if (TestContext.CurrentTestOutcome == UnitTestOutcome.Passed)
return;
var filename = Path.GetRandomFileName() + ".png";
using (var screenshot = ScreenCapture.CaptureDesktop())
screenshot.Save(filename, ImageFormat.Png);
TestContext.AddResultFile(filename);
}
}
Screenshot class
public class ScreenCapture
{
public static Image CaptureDesktop()
{
// Determine the size of the "virtual screen", which includes all monitors.
var screenLeft = SystemInformation.VirtualScreen.Left;
var screenTop = SystemInformation.VirtualScreen.Top;
var screenWidth = SystemInformation.VirtualScreen.Width;
var screenHeight = SystemInformation.VirtualScreen.Height;
// Create a bitmap of the appropriate size to receive the screenshot.
var screenshot = new Bitmap(screenWidth, screenHeight);
// Draw the screenshot into our bitmap.
using (Graphics g = Graphics.FromImage(screenshot))
g.CopyFromScreen(screenLeft, screenTop, 0, 0, screenshot.Size);
return screenshot;
}
}
Drawbacks are that you might not want to inherit a single base class for all tests and that the actual file doesn't seem to be attached in the report, only the path. If you're using this in a CI tool archiving it should be simple enough though.
Also this screen capture class (got it from here) is very simplistic and has a dependency on the Windows.Forms dll, I used it because it was simple to get the entire multi screen desktop shot. Here's another example of how to do it i.e. per window.