SeleniumHQ / selenium-google-code-issue-archive

Archive, please see main selenium repo
https://github.com/seleniumhq/selenium
345 stars 195 forks source link

Unable to capture screenshot using Augmented RemoteWebDriver for odd versions of Internet Explorer #2423

Closed lukeis closed 8 years ago

lukeis commented 8 years ago

Originally reported on Google Code with ID 2423

Hopefully the summary got your curiosity up so you are reading this.  I have been learning
Selenium starting with 2.0RC2 and found the original Selenium 1.0 API much easier to
use than the WebDriver API.  However, since WebDriver appears to be the future direction
I have made my code use it, although I do depend on the WebDriverBackedSelenium to
wrap how to implement some of the functionality.

Selenium version: 2.5.0
OS: Windows Vista running the tests and the Grid server, with Windows XP for IE6 &
IE7, Vista (same as the grid) or XP for IE8, and Windows 7 for IE9.
Browser: IExplore
Browser version: 6, 7, 8, and 9

What has been an issue for me is getting a screenshot at the time of a test failure.
 Since my tests will be running overnight on many browser versions this is CRITICAL!
 So I was very disappointed to find that that functionality did not exist by default.

I then found this thread is the discussion group:
http://groups.google.com/group/selenium-users/browse_thread/thread/55066381d492c716

Using that I have gotten code that works for getting a screenshot for Firefox, Chrome,
and Opera with no problems.  However, Internet Exploder is a different story.  I though
it simply did not work at all, but in having my tests run last night I saw that I did
get a screenshot for both IE6 and IE8.  The initial one for IE6 was simply a white
box, I think due to having a pop-up open, but rerunning it this morning got me a good
screenshot.  I am not sure that IE8 was giving me screenshots 100% of the time earlier
in my testing, but I might have been using IE9 then, I simply am not sure.  The issue
that need to be resolved is why this is so hit and miss.

When this fails I get an exception with the following message:
org.openqa.selenium.remote.RemoteWebDriver$$EnhancerByCGLIB$$60bbe7c1 cannot be cast
to org.openqa.selenium.TakesScreenshot

I do not report a stack trace in my code at that point, but can provide one if so desired.
 My Java test code runs on the same Vista system as the Grid hub is on.  That system
also provides one of the IE8 versions available to run, with the other one being on
my Windows XP desktop.

Here is the code I am using to create the snapshot.  It is used to report an exception
being caught, or if there is none to simply report a message to the TestNG log and
supply a screenshot, which you should be able to drop into any existing test case using
WebDriver to use:

    /**
     * This is used to create a selenium object that is backed by a Web Driver.
     */
    public WebDriver webDriver;  // Used for WebDriver and RemoteWebDriver

    /**
     * This is used when trying to capture a screenshot at the time of failure.
     * This is based on a recommendation from the Selenium user group:
     * <a href="http://groups.google.com/group/selenium-users/browse_thread/thread/55066381d492c716#">
     * Automatic Screenshot on error</a>
     * @return WebDriver generated by Augmenter class.
     */
    private WebDriver getScreenshot()
    {
        return new Augmenter().augment(webDriver);
    }   // getScreenshot

    /**
     * This method is simply used to output a blank line to both the console and
     * the reporter log.  The funny thing about Reporter.log() is that if you
     * use the method that goes to both then it will not handle XHTML tags and
     * seems to just send them out as-is to the console.  So instead of doing
     * two calls every time I need a blank line (one for console and one for the
     * log), I just wrote this method to do it.
     */
    private void logBlankLine()
    {
        System.out.println(""); // Output a blank line on the console
        Reporter.log("<br />"); // Output a blank line in the log
    }   // logBlankLine

    /**
     * This is used to log any exception that happens during a test.  It must be
     * called from the test, but it will not flag the test as having failed, as
     * the exception might be what was expected.  The stack trace, exception
     * message string, and explanation are all written to the console as well as
     * the Reporter log (which is part of the TestNG Results page).  In addition
     * a screenshot is captured to a file and an img tag is written out to the
     * Reporter log so it is visible on the web page for Reporter output and
     * Results web pages.  A blank line will be output both before and after the
     * exception info, to help it standout from other output.
     * @param explanation This should be some string that explains what was
     * going on when the exception occurred.  Something that will make sense to
     * the person reading the log.  Can be null if no explanation is provided.
     * @param ex This is anything that is a subclass of Throwable, like
     * Exception.  Can be null for cases where there is no Throwable event to
     * report.
     */
    public void logException(String explanation, Throwable ex)
    {
        logBlankLine();
        if (explanation != null)
            Reporter.log(explanation, true);

        if (ex != null)
            Reporter.log(ex.getMessage(), true);

        if (webDriver == null)
        {   // This is not currently supported on Webdriver
            if (selenium != null)
            {
                String str = System.getProperty("user.dir") + "\\"; // Current dir

                selenium.captureScreenshot(reportDir + "\\ScreenSnapshot.PNG");
                Reporter.log("<img src=\"file:///" + str + reportDir +
                             "\\ScreenSnapshot.PNG\" alt=\"\"/><br />");
            }
        }   // if
        else
        {   // Not all Webdriver instances can take a screenshot
            WebDriver driver = getScreenshot();
            //if (webDriver instanceof TakesScreenshot)
            {   // This one can take a screenshot
                try
                {
                    File file;
                    String str = System.getProperty("user.dir") + "\\"; // Current
dir

                    file = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
                    FileUtils.copyFile(file, new File(reportDir +
                                                      "\\ScreenSnapshot.PNG"));
                    Reporter.log(
                            "<img src=\"file:///" + str + reportDir +
                            "\\ScreenSnapshot.PNG\" alt=\"\"/><br />");
                }
                catch (Throwable ex1)
                {
                    Reporter.log("Unable to capture screentshot to " +
                                 "ScreenSnapshot.PNG\nGot error: " +
                                 ex1.getMessage());
                }   // try-catch
            }   // if
        }   // else

        logBlankLine();
    }   // logException

Reported by lvskiprof on 2011-09-08 18:26:11

lukeis commented 8 years ago
Make that confirmed that it is a bit random as to when it fails to get the screenshot.
 I just now manually ran each version one at a time and each version was able to get
a screenshot this time.

It is possible that the error is due to a timeout issue.  I had 10 copies of the same
test running through the hub at the same time, spread across 4 VMs and my desktop (all
the VMs are on the same system, as is the hub).  I did notice one time running the
IE6 test from within my IDE that it failed to close the browser on the VM and that
was also a time when it did not grab a screenshot (which happens at the end of this
test just before I do the seleniun.stop() using my WebDriverBackedSelenium instance).

Hopefully this will clue someone in that knows the code as to what is going on.

Reported by lvskiprof on 2011-09-08 22:06:02

lukeis commented 8 years ago
I was just running some requested tests for 2426 and I got the error twice in a row
with IE7 where the screenshot fails and got to see it.  I have noticed a few times
that when I run IE or Firefox (the only two I have seen this happen with so far) that
I sometimes never see the browser show up on the desktop of the system it is running
one, yet that test does run and completes successfully.  All my test does is log onto
a web site and exit back out of it, verifying that you end up on the correct pages
as it goes.

What happened now is that I see the program finishing up, based on the status output
of the RemoteWebDriver server.  But when I go to look for a screenshot in the results
web page created by TestNG methods in my code it is not there.  So this must be tied
to times when the web browser is not showing up on the desktop, which is not 100% of
the time.

I think if you figure out why that happens you will have an explanation as to why screenshots
are failing sometimes, but not others.

Here is the status from the end of that test.  It clicks a button to logout, waits
for the page title to change back to the login screen, and it is then supposed to capture
the screenshot and close the session:

09:13:59.264 INFO - Executing: [find element: By.selector: button] at URL: /session/1315584576666/element)
09:13:59.264 INFO - Done: /session/1315584576666/element
09:13:59.280 INFO - Executing: [click: 5 org.openqa.selenium.support.events.EventFiringWebDriver$EventFiringWebElement@223be4]
at URL: /session/1315584576666/element/5/click)
09:13:59.389 ERROR - runtimeError: message=[The data necessary to complete thisoperation
is not yet available.] sourceName=[http://iiscf1a/scripts/jquery/jquery-1.5.1.min.js]
line=[16] lineSource=[null] lineOffset=[0]
09:13:59.389 WARN - getElementById(script1315584839389) did a getElementByName for
Internet Explorer
09:13:59.592 INFO - Done: /session/1315584576666/element/5/click
09:13:59.608 INFO - Executing: [get title] at URL: /session/1315584576666/title)

09:13:59.608 INFO - Done: /session/1315584576666/title
09:13:59.624 INFO - Executing: [get title] at URL: /session/1315584576666/title)

09:13:59.624 INFO - Done: /session/1315584576666/title
09:13:59.999 INFO - Executing: [delete session: 1315584576666] at URL: /session/1315584576666)
09:13:59.999 INFO - Done: /session/1315584576666
09:14:00.467 INFO - Executing: org.openqa.selenium.remote.server.handler.Status@1dd1ed2
at URL: /status)
09:14:00.483 INFO - Done: /status

Here is one where the screenshot worked:

09:29:36.450 INFO - Done: /session/1315583763948/execute
09:29:36.465 INFO - Executing: [find element: By.selector: button] at URL: /session/1315583763948/element)
09:29:36.496 INFO - Executing: org.openqa.selenium.remote.server.handler.Status@191e0eb
at URL: /status)
09:29:36.496 INFO - Done: /status
09:29:36.528 INFO - Done: /session/1315583763948/element
09:29:36.543 INFO - Executing: [click: 5 org.openqa.selenium.support.events.EventFiringWebDriver$EventFiringWebElement@139cb14d]
at URL: /session/1315583763948/element/5/click)
09:29:36.668 INFO - Done: /session/1315583763948/element/5/click
09:29:36.668 INFO - Executing: [get title] at URL: /session/1315583763948/title)

09:29:37.059 INFO - Done: /session/1315583763948/title
09:29:37.059 INFO - Executing: [get title] at URL: /session/1315583763948/title)

09:29:37.075 INFO - Done: /session/1315583763948/title
09:29:37.465 INFO - Executing: [take screenshot] at URL: /session/1315583763948/screenshot)
09:29:38.012 INFO - Done: /session/1315583763948/screenshot
09:29:38.137 INFO - Executing: [delete session: 1315583763948] at URL: /session/1315583763948)
09:29:38.418 INFO - Executing: org.openqa.selenium.remote.server.handler.Status@cb800f
at URL: /status)
09:29:38.418 INFO - Done: /status

Reported by lvskiprof on 2011-09-09 16:31:43

lukeis commented 8 years ago
How to use the logException function? And the logs are output on console or reporter?

Thanks

Reported by blusunrui on 2011-09-13 07:24:36

lukeis commented 8 years ago
The logs are output on both, except for the screenshot itself.  I created the logBlankLine()
method because if you output to both the <br/> tag does not get interpreted, but gets
output literally.  The version of Report.log() that goes only to the log itself is
able to properly handle HTML tags.

Reported by lvskiprof on 2011-09-20 15:52:38

lukeis commented 8 years ago
Looking at the logs from the remote server sessions, it looks like getScreenshotAs()
is never called at all in the session where you see no screenshot generated. Is it
possible this line of code is in an decision branch that's not getting executed?

Reported by james.h.evans.jr on 2011-09-20 19:27:03

lukeis commented 8 years ago
No that is not possible, because you see the message from the catch that says it was
not able to capture the screenshot.

I filed this bug after I saw this happen while I was running the test case manually
from within the IDE with the VM console in front of me.  It happened when the browser
was never visible on the desktop console, yet the code was obviously running a browser
somewhere.  I could see the status messages going by in the command line windows for
the server and all the tests passed.  It is failing to get the screenshot, from what
I can see, because the browser is not visible on the desktop.

This is a rare event, but I saw it happen twice that day, and then I didn't see it
again.  I have been doing updates with each new version and am currently locked in
with 2.5.0 and I have not seen this error in a while.  I have 6 tests run every night,
but I don't always drill down to where the image would show up.

Reported by lvskiprof on 2011-10-03 17:08:28

lukeis commented 8 years ago

Reported by barancev on 2011-10-13 09:05:10

lukeis commented 8 years ago

Reported by jmleyba on 2012-01-04 03:28:51

lukeis commented 8 years ago
Hi!

i can not reproduce it at my Vista x32, ie9, selenium 2.32

Is it still reproducible?
2.0 is really old so please update to last selenium before reproducing.
Also please provide full exception info, grid hub&node configuration (cmd startup lines),
logs and test scenario.

My test code:
-------------------------------------------------------------------
public class Main {
    public static void main(String[] args) {

        Capabilities c = DesiredCapabilities.internetExplorer();

        WebDriver driver = new RemoteWebDriver(c);

        driver.get("http://localhost/www/screen/screen_too_long.html");

        try {
            WebDriver augemented = new Augmenter().augment(driver);
            File file = ((TakesScreenshot) augemented).getScreenshotAs(OutputType.FILE);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            driver.quit();
        }
    }
}
--------------------------------------------------------------------

Reported by a.u.savchuk on 2013-05-06 17:53:16

lukeis commented 8 years ago
Closing due to inactivity. Please ask to reopen if the issue is still actual.

Reported by barancev on 2013-08-14 20:39:13

lukeis commented 8 years ago

Reported by luke.semerau on 2015-09-17 18:13:39