Selenium and Chromedriver on Lambda - Inconsistency at scale - selenium

I have a basic selenium script running/deployed on aws lambda.
Chrome and chromedriver and installed as layers (and available on /opt) via serverless.
The script works ... but only some of the time and rarely at scale (invoking more than 5 instances asynchronously).
I invoke the function in a simple for loop (up to about 200 iterations)
response = client.invoke(
FunctionName='arn:aws:lambda:us-east-1:12345667:function:selenium-lambda-dev-hello',
InvocationType='Event', #|'RequestResponse'|'Event' (async)| DryRun'
LogType='Tail',
#ClientContext='string',
Payload=event_payload,
#Qualifier='24'
)
Other runs, the process hangs while initiating the selenium driver on this line
driver = webdriver.Chrome('/opt/chromedriver_89', chrome_options=options)
other iterations the drivers fail/throw a 'timeout waiting for renderer exception'
This I believe is often due to a mismatch of chromedriver/chrome. I have checked and verified my versions are matched up and compatible (and like i said they do work sometimes).
I guess i'm looking for some ideas/direction to even begin to troubleshoot this. I was under the impression that each invokation of a lambda function is in a separate environment, so why would increasing the volume of invokations have any adverse effect on how well my script runs?
Any ideas or thoughts would be greatly appreciated all!

Discussed in the comments.
There's no complete solution but what has helped improve the situation was increasing the memory of the Lambda service.
The alternatives to try/consider:
Don't use Chrome. Use requests and lxml to query the pages via the network level and remove the need for Chrome.
I did something similar to support another stack question recently. You can see it's similar but not quite the same.
Go to a url and get some text from an xpath:
from lxml import html
import requests
import json
url = "https://nonfungible.com/market/history"
response = requests.get(url)
page = html.fromstring(response.content)
datastring = page.xpath('//script[#id="__NEXT_DATA__"]/text()')
Don't use Chrome. Chrome is ideal for functional testing - but if that's not you objective consider using HtmlUnitDriver or phantomjs. Both of these are significantly lighter than chrome and won't require a browser to be installed (you can run it straight from libraries)
You only need to change the driver initialisation and the rest of the script (in theory) should work.
PhantomJS:
$ pip install selenium
$ brew install phantomjs
from selenium import webdriver
driver = webdriver.PhantomJS()
Unit Driver:
from selenium import webdriver
driver = webdriver.Remote(
desired_capabilities=webdriver.DesiredCapabilities.HTMLUNIT)

Related

How to disable automatic updates of Chrome when run with Selenium?

I have an automatic test suite that uses Selenium to control a Chrome browser with a particular version. However Chrome tries to update itself between test runs. How do I prevent Chrome from automatically updating itself?
Removing write permission from the Google Chrome binary appears to prevent it from self-updating, at least on macOS.
In Python you can do that with code that looks like:
import subprocess
def remove_write_permissions(itempath: str) -> None:
subprocess.run([
'chmod',
'-R',
'a-w',
itempath
], check=True, capture_output=True)
remove_write_permissions('/Applications/Google Chrome.app')
I've only tested this code on macOS. It probably also works on Linux, but probably not Windows.

The method attachToEdgeChrome() is undefined for the type InternetExplorerOptions using selenium-server-4.0.0-alpha-2

I want test the IE mode for Edge browser with Selenium. I found the solution on the MS site here:
https://learn.microsoft.com/en-us/microsoft-edge/webdriver-chromium/ie-mode?tabs=java
I am using the following code as given in the above link:
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.openqa.selenium.ie.InternetExplorerOptions;
InternetExplorerOptions ieOptions = new InternetExplorerOptions();
ieOptions.attachToEdgeChrome();
ieOptions.withEdgeExecutablePath("C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe");
WebDriver driver = new InternetExplorerDriver(ieOptions);
I can get the error that the methods "attachToEdgeChrome()" and "withEdgeExecutablePath()" are not defined in the InternetExplorerOptions. Is there anything I am missing here?
Note: My selenium jar is selenium-server-4.0.0-alpha-2.jar
As per the ChangeLogs 0f Selenium v4.0.0.0-alpha-2:
Add Chromium-based Edge support. This involves adding a new Chromium driver to the tree too.
So ideally, the code block from the documentation Use Internet Explorer Driver to automate IE mode in Microsoft Edge should have worked seamlessly.
However, as per best practices instead of using the alpha and beta releases, you should always prefer the GA releases to execute your tests and you can pickup anyone from the following options:
Selenium v4.1.3
Selenium v4.1.2
Selenium v4.1.1
Selenium v4.1.0
Selenium v4.0.0

"Component not initialized" nsresult: "0xc1f30001 (NS_ERROR_NOT_INITIALIZED)" error with Selenium GeckoDriver and Mozilla

I am trying to execute my code in Firefox, sometimes it works but majority of time i get exception as:
[Exception... "Component not initialized" nsresult: "0xc1f30001 (NS_ERROR_NOT_INITIALIZED)" location: "JS frame :: chrome://marionette/content/dom.js :: addEventListener :: line 67" data: no]
Its happening from last week, previously it was working fine for me.
NS_ERROR_NOT_INITIALIZED resembles an attempt which was made to use a component or object which has not yet been initialized. These components usually provide an initialization method, often called Init which must be called before any other methods which are being used.
However, this error message...
[Exception... "Component not initialized" nsresult: "0xc1f30001 (NS_ERROR_NOT_INITIALIZED)" location: "JS frame :: chrome://marionette/content/dom.js :: addEventListener :: line 67" data: no]
...implies that the Marionette threw an error while invoking addEventListener as defined in dom.js
Your code trials and the relevant HTML DOM would have helped us to debug the issue in a better way. However it seems the addEventListener was invoked too early even before the DOM Tree was completely rendered. To be more specific addEventListener was invoked even before the Browser Client (i.e. the Web Browser) have attained 'document.readyState' equal to "complete". Generally once this condition is fulfilled Selenium performs the next line of code.
Solution
A quick solution will be to before you try to interact with any of the element on a fresh loaded webpage you need to induce WebDriverWait for either of the following expected_conditions:
title_is(title)
title_contains(title)
An example
Python:
Code Block:
driver.get("https://stackoverflow.com");
WebDriverWait(driver, 10).until(EC.title_contains("Stack"))
print("Page Title is : "+driver.title)
Console Output:
Page Title is : Stack Overflow - Where Developers Learn, Share, & Build Careers
Java:
Code Block:
driver.get("https://stackoverflow.com");
new WebDriverWait(driver, 10).until(ExpectedConditions.titleContains("Stack"));
System.out.println("Page Title is : "+driver.getTitle());
Console Output:
Page Title is : Stack Overflow - Where Developers Learn, Share, & Build Careers
Additional Considerations
Upgrade JDK to recent levels JDK 8u221.
Upgrade Selenium to current levels Version 3.141.59.
Upgrade GeckoDriver to GeckoDriver v0.25.0 level.
Ensure that the version of the binaries you are using are compatable.
You can find a detailed discussion in Which Firefox browser versions supported for given Geckodriver version?
GeckoDriver is present in the desired location.
GeckoDriver is having executable permission for non-root users.
Upgrade Firefox version to Firefox v69.0 levels.
Clean your Project Workspace through your IDE and Rebuild your project with required dependencies only.
If your base Web Client version is too old, then uninstall it and install a recent GA and released version of Web Client.
Take a System Reboot.
Execute your Test as a non-root user.
Always invoke driver.quit() within tearDown(){} method to close & destroy the WebDriver and Web Client instances gracefully.
References
You can find a couple of relevant discussions in:
WebDriverException: Message: Exception… “Failure” nsresult: “0x80004005 (NS_ERROR_FAILURE)” while saving a large html file using Selenium Python
[org.openqa.selenium.WebDriverException: Exception… “Component not initialized” error using GeckoDriver and Tor browser with Selenium Java
Outro
Occur the 'NS_ERROR_NOT_INITIALIZED' when switching the window to bottom dock.
It seems you're suffering from Geckodriver Issue 1263, you can try the following workarounds:
Update Selenium client library to the latest stable which is 3.141.59 as of now, it's better to use package management system like Maven or Gradle as update of dependencies libraries might be required. If you're not using Java check out Web - Desktop and Mobile Browsers article for code examples for different Selenium client languages like JavaScript, Python, C#, etc.
Make sure to use the latest version of Firefox
Make sure to use the latest version of Geckodriver
If you will be still experiencing problems you can consider raising a new issue in the Geckodriver project, be prepared to provide as much information as possible (the same applies to next questions here if any)
On my case, some configs were wrong. I was trying to block pop-up downloads, but something went wrong.Here is the code that I had to remove, and it worked (on this specific case):
FirefoxProfile profile = new FirefoxProfile();
profile.setPreference("browser.download.dir", "C:\\Temp");
profile.setPreference("browser.helperApps.neverAsk.saveToDisk", "text/csv");
profile.setPreference("pdfjs.disabled", true);
profile.setPreference("browser.download.folderList", 2);
profile.setPreference("browser.download.panel.shown", false);
DesiredCapabilities capabilities = DesiredCapabilities.firefox();
capabilities.setCapability(FirefoxDriver.PROFILE, profile);
capabilities.setCapability(CapabilityType.ELEMENT_SCROLL_BEHAVIOR, 1);
driver = new FirefoxDriver(capabilities);

Unable to load webextension in firefox using python selenium

Hi I am seeing this issue when I try to load a Firefox webextension using Python Selenium:
selenium.webdriver.firefox.firefox_profile.AddonFormatError: ("[Errno 2] No such
file or directory: 'c:\\users\\admini~1\\appdata\\local\\temp\\tmpr
wj4ed.xxx.xpi\\install.rdf'", )
Code is as below
from selenium import webdriver
extn_path = "C:\Program Files (x86)\xxxxx\xxx.xpi"
profile = webdriver.FirefoxProfile()
profile.add_extension(extn_path)
self.browser=webdriver.Firefox(profile,executable_path='xxx\geckodriver.exe')
Versions used
Selenium 3.12
Gecko v.0.20
Firefox- 60
Can anyone let me know why I am facing this issue. I did see that many people are facing this issue and it's mentioned that it's a known issue but with latest Selenium and Gecko driver issue it is expected to be resolved.
However, I don't see it working. Any tips or inputs.
can you try double front slash instead one single front slash inside your path

Using Selenium 2.0 WebDriver in practice

I want to write Selenium test cases in JUnit and test my projects in multiple browsers and I would like to take advantage of the fact that all Selenium drivers implement the same interface.
Each test case should look like this:
package fm;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import static org.junit.Assert.*;
public class HomepageTest {
#Test
public void testTitle(WebDriver driver) {
driver.get("http://localhost/");
assertEquals("Foo", driver.getTitle());
}
#Test
public void testSearchForm(WebDriver driver) {
//...
}
}
The passed WebDriver implementations should be controlled somewhere centrally. I'll probably need to override some of the JUnit behaviour and I hope it's possible.
I want to do it this way in order to avoid two things:
Code repetition: If each test case would initialize all tested browsers in #Before, the test suite would have a lot of repeated code that is hard to maintain.
Speed of the test suite: If I had centralized control over the order and passed WebDriver implementations, I could easily manage to open for example Firefox, run all test cases in it, close it and open the next browser. If each test case would manage to open and close browsers on its own, it would add a lot of time to each test run.
Anybody have an idea how should I do it? Thanks.
In the Selenium project we inject what we need using http://code.google.com/p/selenium/source/browse/trunk/java/client/test/org/openqa/selenium/AbstractDriverTestCase.java and then our build calls the browser and we get tests running in it.
Have a look at our code base to get some inspiration!
Please check with ISFW it supports selenium webdriver/remote webdriver as well as conventional (selenium1) rc way.
You need to write code using regular selenium api
for example
selenium.open(url);
selenium.type("loc", "text to type");
selenium.submit("loc");
Here is the working demo. Set browser String as per your requirement.
The FW support selenium conventional way as well as selenium 2 webdriver. You need to set appropriate browser string in application properties. Following are different browser configurations for Firefox:
*firefox - required selenium server running on configured host/port
if not found then fw will check/start one on locahost/port
firefoxDriver – will run directly with firefox web driver without
selenium server
firefoxRemoteDriver - required selenium server running on
configured host/port if not found then fw will check/start one on
locahost/port, it will run test using firefox web driver on host
machine
Same way for IE - *iexplore, *iehta, iexplorerDriver, iexplorerRemoteDriver
and so on.
I did what you are/were? trying to do with a static class that controlls the webdriver and all my test which need the same webdriver get it from there. It really helps when you are running multiple tests that need to use the same session. And all your tests run in one browser, so not every tests opens a new browser instance.
Maybe you should also have a look at testNG. I made the experience that testNG is better for tests with selenium since it is not so focused on independent tests. It offers a lot of useful functionality.