views:

2339

answers:

7

I would like an automated web tests suite based on Selenium RC to take screenshots of pages when some errors are encountered. The test suite is a part of the continuous integration process and technically is executed by CruiseControl running as a Windows service.

The selenium.captureScreenshot() method is called to trigger the actual screenshot. I've registered a JUnit RunListener to call it on any test failure.

The problem is the screenshots are just blank files - PNG files totally black. The dimensions are 1440x900.

When manually running the same tests from Eclipse the screenshots are OK (althought they are screenshots of the whole desktop not the browser window, but that's a different story and a minor issue). So I guess the cause of the problem is the Selenium being run as a Windows service.

How can I have the screenshots of pages taken when exceptions in Selenium tests happen?

The software used:

  • Windows 2003 Server
  • Selenium 1.0.1
A: 

Here is some code for taking pics using Selenium and the Java Robot class:

public void takeAScreenShotOfTheApp() {
  Dimension screenDim = Toolkit.getDefaultToolkit().getScreenSize();
  Rectangle screenBounds = new Rectangle(0, 0, screenDim.width, screenDim.height);

  Robot robot = new Robot();
  BufferedImage image =  robot.createScreenCapture(screenBounds);

  File screenshotFile = new File("target" + File.separator
                               + "image" + System.currentTimeMillis() + ".png");
  ImageIO.write(image, "png", screenshotFile);
}

It is taken from this site

shambleh
Thanks. I will give this one a try. But I doubt it could help. I've seen this site before. And actually Selenium implementation of the 'captureScreenshot' command seems to use exactly the same technique: http://tinyurl.com/Selenium1260106
Grzegorz Oledzki
@GrzegorzOledzki - I suspected that Selenium may be taking the same approach. Please let us know if it works and good luck.
shambleh
Confirmed. The behaviour is exactly the same. The robot generated a completely blank (black) image with exactly the same size. So, no progress...
Grzegorz Oledzki
I tried to do some checking around with other Selenium people, but they haven't encountered the issue. If there is not another way to go about this, contacting Selenium and logging a bug may help clear up the issue.
shambleh
Wild stab-in-the-dark.... does the screensaver kick-in and affect screenshots? What if you disable the (blank) screen-saver completely?
searlea
Screensaver: The user the service is running as had a screensaver defined, but not a blank screen one. It was some waving Microsoft logo. Either way, I've turned off the screensaver for the user and the result is the same.
Grzegorz Oledzki
+2  A: 

Reading a little more on this, it could be something to do with your windows service needing extra security permissions. Going back to Windows NT 3.5/4 services had restricted access to the application desktop (required for screenshots) and I'd guess their security restrictions continue to this day.

This thread about services on the java.net forums may provide the clues you need to get it working.

searlea
The java.net link seems to suggest using VNC connection to localhost. I see it as a last resort. If a remote call is needed, then nothing should stop us from calling the selenium server on a Linux machine with a proper Xserver support. But that complicates the build infrastructure a lot and I hope this could be avoided.
Grzegorz Oledzki
+2  A: 

What browser are you running these tests in? If it's Firefox I'd recommend the captureEntirePageScreenshot to capture the entire canvas - not just what's in view (rather than the screen) and captureEntirePageScreenshotToString if you're working remotely and want to save the files locally.

Not sure if it will help with your issue, but as it uses an add-on to Firefox it might be worth a try.

Dave Hunt
Firefox is used. Not really sure which version, I would have to check it. Anyway, thanks for the tip - I will check it.
Grzegorz Oledzki
Hm... I was about to write that the suggestion worked. Because it has given proper screenshots once or twice. But something broke again and now I keep getting blank files again. Now the dimensions differ - sometimes it's 978x36 and sometimes it's 978x232 (depending on the actual test being invoked), but still 100% black PNG.Aaah. I thought it's solved.
Grzegorz Oledzki
I've seen a black PNG once or twice, but most of the time it works fine for me. I'm not running as a service though... Hope you find something that works.
Dave Hunt
+1  A: 

I have come accross the issue with CaptureScreenshot generating black images when running under a windows service.

Using CaptureEntirePageScreenshot as recommended by Dave Hunt is working consistently for me.

DownChapel
Unfortunately. I have seen non-black screenshots taken by captureEntirePageScreenshot() only once. Just after switching it (instead of captureScreenshot()). But since then it doesn't work.
Grzegorz Oledzki
+3  A: 

Looks like there's a completely different answer. The Windows service (managed by TanukiSoftware Java Service Wrapper) was started with wrapper.ntservice.interactive set to false. Setting it to true has helped. Eventually the screenshots contain real screen content.

Consult the wrapper.ntservice.interactive for details. The analysis of the wrapper code leads to SERVICE_INTERACTIVE_PROCESS flag being set when starting the Windows service.

Grzegorz Oledzki
A: 

I don't know how cruise control will execute GUI tests, but i recently implemented a screenshot mechanism myself and what i learned was that the components you're drawing have to be in a window or some other root element. "unrooted" elements will just not paint properly and result in black images most of the time.

So if cruise control or your unit tests are using some magic to not properly display the gui elements, you might want to add them to a dummy JFrame before painting.

Stroboskop
A: 

An alternative solution to your RunListener approach:

Enclose your test in a try-catch block and do the screenshot in the catch block, that's what i always do.

Example java code:

public void testEnterFormFields()
  try {
    enterFormFields();
  } catch(SeleniumException e) {
    //do screenshot, logging, dumping, stacktracing or whatever here
  }
}

You could catch Throwable or Exception as well, if your coding rules allow it, but it makes sense to catch the specific Exception one by one. This approach produces a bit more clutter in your code but it will help you a lot in case of failure analysis. You can tailor your exception handling to the type of error. You maybe want to capture other informations in case of an AssertionError than in case of a SeleniumException.

ruby fu novice
How does it answer the problem of blank screenshots?
Grzegorz Oledzki
This way you are taking screenshots before exiting the test method -> before any errors are reported and teardown methods are called that will destroy the browser instance.
ruby fu novice