SeleniumHQ / selenium-google-code-issue-archive

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

NullPointerException in Android WebDriver (Caused by JavaScript timeout) #4112

Closed lukeis closed 8 years ago

lukeis commented 8 years ago

Originally reported on Google Code with ID 4112

I have been trying to use Selenium WebDriver on the Android emulator. However, sometimes
I am getting a NullPointerException from within the WebDriver server while running
simple test examples from the documentation. I also believe that I have traced the
problem to the org.openqa.selenium.android.library.AndroidWebDriver class.

I've been trying to run the test method for google's homepage listed on the AndroidDriver
page:
(code from http://code.google.com/p/selenium/wiki/AndroidDriver#Run_the_Tests)

  public void testGoogle() throws Exception {
    WebDriver driver = new AndroidDriver();

    // And now use this to visit Google
    driver.get("http://www.google.com");

    // Find the text input element by its name
    WebElement element = driver.findElement(By.name("q"));

    // Enter something to search for
    element.sendKeys("Cheese!");

    // Now submit the form. WebDriver will find the form for us from the element
    element.submit();

    // Check the title of the page
    System.out.println("Page title is: " + driver.getTitle());
    driver.quit();
  }

What steps will reproduce the problem?
1. Create and launch the Android emulator 
2. Install and launch the WebDriver app
3. Run the test from any remote machine to control the Android WebDriver

(Alternatively, create any situation on Android where javascript executed in the WebView
takes longer than 10 seconds to return and the javascript return value is dereferenced)

What is the expected output? What do you see instead?
I expect the test to complete successfully every time, printing the page title to standard
output. Instead, sometimes (roughly 25% of the tim in my testing) an unhandled NullPointerException
is thrown on the Android WebDriver server and returned to the client.

The stack trace printed out in eclipse shows that the NullPointerException is thrown
at AndroidWebElement.isEnabled() line 222 which is called from AndroidWebElement.sendKeys(CharSequence...)
line 173. However, while debugging, I got a deeper stack trace of the problem (my comments
in asterisks):

AndroidWebDriver.executeRawScript(String) line: 863 **null is returned because executeJavascriptInWebView()
returned null on line 860.**

AndroidWebDriver.executeAtom(String, Object...) line: 882   

AndroidWebElement.isEnabled() line: 222 **tries to cast the null-valued String to Boolean.
NullPointerException is thrown.**

AndroidWebElement.sendKeys(CharSequence...) line: 173

Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) line: not
available [native method]   

Method.invoke(Object, Object...) line: 511  

(Remaining stack trace trimmed…)

Selenium version: selenium-server-2.21.0.apk
OS: Android 4.0.3
Browser: The one bundled with Android
Browser version: Here's my User Agent: Mozilla/5.0 (Linux; U; Android 4.0.4; en-us;
sdk Build/MR1) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30

---

I believe I have tracked the source of this bug to the executeJavascriptInWebView()
function within the AndroidWebDriver class in the package org.openqa.selenium.android.library.
While executeJavascriptInWebView() is called from many functions besides sendKeys(),
here javascript is used to check if the element is enabled (!element.disabled in javascript)
and get the tag name of the element (such as the HTML <input> tag).

executeJavascriptInWebView() first sets the variable “result” to null, then waits for
the javascript thread to notify it that result is set. However, if the javascript execution
times out, it simply returns as usual but without result being set, giving null to
the calling thread. Returning null is not necessarily an error, since many times executed
javascript changes something on the page, but doesn’t return anything. However, a script
timeout should probably always be an error.

In AndroidWebDriver.java, there is a hard-coded timeout of 10 seconds enforced for
any javascript that WebDriver has run and is waiting on. On most platforms this is
probably plenty of time, but while running this test with google's webpage on an (very
slow) Android emulator, the javascript actually takes just about 10 seconds to run.
So, sometimes WebDriver will time out while waiting for the asynchronous javascript.
For my own purposes, I have simply increased the timeout from 10 seconds to 1 minute,
and re-built the apk.

What should probably happen though is for the method to throw an appropriate and descriptive
exception for timeouts. Perhaps a TimeoutExcpetion would be appropriate, unless that
is ambiguous to timeouts occurring for finding elements (the user-set implicit and
explicit waits). There is actually a setScriptTimeout() method, but it is unimplemented,
along with pageLoadTimeout(). I’m not sure how these are implemented in other WebDrivers,
but I’d imagine the desired behavior could be copied from there.

Thank you,
Braden

Reported by braden@bradenehrat.com on 2012-06-19 21:32:45

lukeis commented 8 years ago

Reported by barancev on 2012-06-19 21:48:07

lukeis commented 8 years ago
Selenium project no longer supports the AndroidDriver.

Please use Selendroid instead:
http://selendroid.io/webview.html

And log any issues against that project:
https://github.com/selendroid/selendroid/issues

Reported by luke.semerau on 2013-12-26 21:57:35

lukeis commented 8 years ago

Reported by luke.semerau on 2015-09-17 18:15:40