Can Selenium interact with an existing browser session? - selenium

Does anybody know if Selenium (WebDriver preferably) is able to communicate with and act through a browser that is already running before launching a Selenium Client?
I mean if Selenium is able to comunicate with a browser without using the Selenium Server (with could be an Internet Explorer launched manually for example).

This is a duplicate answer
**Reconnect to a driver in python selenium ** This is applicable on all drivers and for java api.
open a driver
driver = webdriver.Firefox() #python
extract to session_id and _url from driver object.
url = driver.command_executor._url #"http://127.0.0.1:60622/hub"
session_id = driver.session_id #'4e167f26-dc1d-4f51-a207-f761eaf73c31'
Use these two parameter to connect to your driver.
driver = webdriver.Remote(command_executor=url,desired_capabilities={})
driver.close() # this prevents the dummy browser
driver.session_id = session_id
And you are connected to your driver again.
driver.get("http://www.mrsmart.in")

This is a pretty old feature request: Allow webdriver to attach to a running browser . So it's officially not supported.
However, there is some working code which claims to support this: https://web.archive.org/web/20171214043703/http://tarunlalwani.com/post/reusing-existing-browser-session-selenium-java/.

This snippet successfully allows to reuse existing browser instance yet avoiding raising the duplicate browser. Found at Tarun Lalwani's blog.
from selenium import webdriver
from selenium.webdriver.remote.webdriver import WebDriver
# executor_url = driver.command_executor._url
# session_id = driver.session_id
def attach_to_session(executor_url, session_id):
original_execute = WebDriver.execute
def new_command_execute(self, command, params=None):
if command == "newSession":
# Mock the response
return {'success': 0, 'value': None, 'sessionId': session_id}
else:
return original_execute(self, command, params)
# Patch the function before creating the driver object
WebDriver.execute = new_command_execute
driver = webdriver.Remote(command_executor=executor_url, desired_capabilities={})
driver.session_id = session_id
# Replace the patched function with original function
WebDriver.execute = original_execute
return driver
bro = attach_to_session('http://127.0.0.1:64092', '8de24f3bfbec01ba0d82a7946df1d1c3')
bro.get('http://ya.ru/')

It is possible. But you have to hack it a little, there is a code
What you have to do is to run stand alone server and "patch" RemoteWebDriver
public class CustomRemoteWebDriver : RemoteWebDriver
{
public static bool newSession;
public static string capPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "TestFiles", "tmp", "sessionCap");
public static string sessiodIdPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "TestFiles", "tmp", "sessionid");
public CustomRemoteWebDriver(Uri remoteAddress)
: base(remoteAddress, new DesiredCapabilities())
{
}
protected override Response Execute(DriverCommand driverCommandToExecute, Dictionary<string, object> parameters)
{
if (driverCommandToExecute == DriverCommand.NewSession)
{
if (!newSession)
{
var capText = File.ReadAllText(capPath);
var sidText = File.ReadAllText(sessiodIdPath);
var cap = JsonConvert.DeserializeObject<Dictionary<string, object>>(capText);
return new Response
{
SessionId = sidText,
Value = cap
};
}
else
{
var response = base.Execute(driverCommandToExecute, parameters);
var dictionary = (Dictionary<string, object>) response.Value;
File.WriteAllText(capPath, JsonConvert.SerializeObject(dictionary));
File.WriteAllText(sessiodIdPath, response.SessionId);
return response;
}
}
else
{
var response = base.Execute(driverCommandToExecute, parameters);
return response;
}
}
}

From here, if the browser was manually opened, then remote debugging can be used:
Start chrome with
chrome --remote-debugging-port=9222
Or with optional profile
chrome.exe --remote-debugging-port=9222 --user-data-dir="C:\selenium\ChromeProfile"
Then:
Java:
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
//Change chrome driver path accordingly
System.setProperty("webdriver.chrome.driver", "C:\\selenium\\chromedriver.exe");
ChromeOptions options = new ChromeOptions();
options.setExperimentalOption("debuggerAddress", "127.0.0.1:9222");
WebDriver driver = new ChromeDriver(options);
System.out.println(driver.getTitle());
Python:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
chrome_options = Options()
chrome_options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")
#Change chrome driver path accordingly
chrome_driver = "C:\chromedriver.exe"
driver = webdriver.Chrome(chrome_driver, chrome_options=chrome_options)
print driver.title

Inspired by Eric's answer, here is my solution to this problem for selenium 3.7.0. Compared with the solution at http://tarunlalwani.com/post/reusing-existing-browser-session-selenium/, the advantage is that there won't be a blank browser window each time I connect to the existing session.
import warnings
from selenium.common.exceptions import WebDriverException
from selenium.webdriver.remote.errorhandler import ErrorHandler
from selenium.webdriver.remote.file_detector import LocalFileDetector
from selenium.webdriver.remote.mobile import Mobile
from selenium.webdriver.remote.remote_connection import RemoteConnection
from selenium.webdriver.remote.switch_to import SwitchTo
from selenium.webdriver.remote.webdriver import WebDriver
# This webdriver can directly attach to an existing session.
class AttachableWebDriver(WebDriver):
def __init__(self, command_executor='http://127.0.0.1:4444/wd/hub',
desired_capabilities=None, browser_profile=None, proxy=None,
keep_alive=False, file_detector=None, session_id=None):
"""
Create a new driver that will issue commands using the wire protocol.
:Args:
- command_executor - Either a string representing URL of the remote server or a custom
remote_connection.RemoteConnection object. Defaults to 'http://127.0.0.1:4444/wd/hub'.
- desired_capabilities - A dictionary of capabilities to request when
starting the browser session. Required parameter.
- browser_profile - A selenium.webdriver.firefox.firefox_profile.FirefoxProfile object.
Only used if Firefox is requested. Optional.
- proxy - A selenium.webdriver.common.proxy.Proxy object. The browser session will
be started with given proxy settings, if possible. Optional.
- keep_alive - Whether to configure remote_connection.RemoteConnection to use
HTTP keep-alive. Defaults to False.
- file_detector - Pass custom file detector object during instantiation. If None,
then default LocalFileDetector() will be used.
"""
if desired_capabilities is None:
raise WebDriverException("Desired Capabilities can't be None")
if not isinstance(desired_capabilities, dict):
raise WebDriverException("Desired Capabilities must be a dictionary")
if proxy is not None:
warnings.warn("Please use FirefoxOptions to set proxy",
DeprecationWarning)
proxy.add_to_capabilities(desired_capabilities)
self.command_executor = command_executor
if type(self.command_executor) is bytes or isinstance(self.command_executor, str):
self.command_executor = RemoteConnection(command_executor, keep_alive=keep_alive)
self.command_executor._commands['GET_SESSION'] = ('GET', '/session/$sessionId') # added
self._is_remote = True
self.session_id = session_id # added
self.capabilities = {}
self.error_handler = ErrorHandler()
self.start_client()
if browser_profile is not None:
warnings.warn("Please use FirefoxOptions to set browser profile",
DeprecationWarning)
if session_id:
self.connect_to_session(desired_capabilities) # added
else:
self.start_session(desired_capabilities, browser_profile)
self._switch_to = SwitchTo(self)
self._mobile = Mobile(self)
self.file_detector = file_detector or LocalFileDetector()
self.w3c = True # added hardcoded
def connect_to_session(self, desired_capabilities):
response = self.execute('GET_SESSION', {
'desiredCapabilities': desired_capabilities,
'sessionId': self.session_id,
})
# self.session_id = response['sessionId']
self.capabilities = response['value']
To use it:
if use_existing_session:
browser = AttachableWebDriver(command_executor=('http://%s:4444/wd/hub' % ip),
desired_capabilities=(DesiredCapabilities.INTERNETEXPLORER),
session_id=session_id)
self.logger.info("Using existing browser with session id {}".format(session_id))
else:
browser = AttachableWebDriver(command_executor=('http://%s:4444/wd/hub' % ip),
desired_capabilities=(DesiredCapabilities.INTERNETEXPLORER))
self.logger.info('New session_id : {}'.format(browser.session_id))

It appears that this feature is not officially supported by selenium. But, Tarun Lalwani has created working Java code to provide the feature. Refer - http://tarunlalwani.com/post/reusing-existing-browser-session-selenium-java/
Here is the working sample code, copied from the above link:
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.remote.*;
import org.openqa.selenium.remote.http.W3CHttpCommandCodec;
import org.openqa.selenium.remote.http.W3CHttpResponseCodec;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.Collections;
public class TestClass {
public static RemoteWebDriver createDriverFromSession(final SessionId sessionId, URL command_executor){
CommandExecutor executor = new HttpCommandExecutor(command_executor) {
#Override
public Response execute(Command command) throws IOException {
Response response = null;
if (command.getName() == "newSession") {
response = new Response();
response.setSessionId(sessionId.toString());
response.setStatus(0);
response.setValue(Collections.<String, String>emptyMap());
try {
Field commandCodec = null;
commandCodec = this.getClass().getSuperclass().getDeclaredField("commandCodec");
commandCodec.setAccessible(true);
commandCodec.set(this, new W3CHttpCommandCodec());
Field responseCodec = null;
responseCodec = this.getClass().getSuperclass().getDeclaredField("responseCodec");
responseCodec.setAccessible(true);
responseCodec.set(this, new W3CHttpResponseCodec());
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
} else {
response = super.execute(command);
}
return response;
}
};
return new RemoteWebDriver(executor, new DesiredCapabilities());
}
public static void main(String [] args) {
ChromeDriver driver = new ChromeDriver();
HttpCommandExecutor executor = (HttpCommandExecutor) driver.getCommandExecutor();
URL url = executor.getAddressOfRemoteServer();
SessionId session_id = driver.getSessionId();
RemoteWebDriver driver2 = createDriverFromSession(session_id, url);
driver2.get("http://tarunlalwani.com");
}
}
Your test needs to have a RemoteWebDriver created from an existing browser session. To create that Driver, you only need to know the "session info", i.e. address of the server (local in our case) where the browser is running and the browser session id. To get these details, we can create one browser session with selenium, open the desired page, and then finally run the actual test script.
I don't know if there is a way to get session info for a session which was not created by selenium.
Here is an example of session info:
Address of remote server : http://localhost:24266. The port number is different for each session.
Session Id : 534c7b561aacdd6dc319f60fed27d9d6.

All the solutions so far were lacking of certain functionality.
Here is my solution:
public class AttachedWebDriver extends RemoteWebDriver {
public AttachedWebDriver(URL url, String sessionId) {
super();
setSessionId(sessionId);
setCommandExecutor(new HttpCommandExecutor(url) {
#Override
public Response execute(Command command) throws IOException {
if (command.getName() != "newSession") {
return super.execute(command);
}
return super.execute(new Command(getSessionId(), "getCapabilities"));
}
});
startSession(new DesiredCapabilities());
}
}

Javascript solution:
I have successfully attached to existing browser session using this function
webdriver.WebDriver.attachToSession(executor, session_id);
Documentation can be found here.

I got a solution in python, I modified the webdriver class bassed on PersistenBrowser class that I found.
https://github.com/axelPalmerin/personal/commit/fabddb38a39f378aa113b0cb8d33391d5f91dca5
replace the webdriver module /usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/webdriver.py
Ej. to use:
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
runDriver = sys.argv[1]
sessionId = sys.argv[2]
def setBrowser():
if eval(runDriver):
webdriver = w.Remote(command_executor='http://localhost:4444/wd/hub',
desired_capabilities=DesiredCapabilities.CHROME,
)
else:
webdriver = w.Remote(command_executor='http://localhost:4444/wd/hub',
desired_capabilities=DesiredCapabilities.CHROME,
session_id=sessionId)
url = webdriver.command_executor._url
session_id = webdriver.session_id
print url
print session_id
return webdriver

Use Chrome's built in remote debugging. Launch Chrome with remote debugging port open. I did this on OS X:
sudo nohup /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222 &
Tell Selenium to use the remote debugging port:
from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_argument('--remote-debugging-port=9222')
driver = webdriver.Chrome("./chromedriver", chrome_options=options)

I'm using Rails + Cucumber + Selenium Webdriver + PhantomJS, and I've been using a monkey-patched version of Selenium Webdriver, which keeps PhantomJS browser open between test runs. See this blog post: http://blog.sharetribe.com/2014/04/07/faster-cucumber-startup-keep-phantomjs-browser-open-between-tests/
See also my answer to this post: How do I execute a command on already opened browser from a ruby file

Solution using Python programming language.
from selenium import webdriver
from selenium.webdriver.remote.webdriver import WebDriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
executor_url = "http://localhost:4444/wd/hub"
# Create a desired capabilities object as a starting point.
capabilities = DesiredCapabilities.FIREFOX.copy()
capabilities['platform'] = "WINDOWS"
capabilities['version'] = "10"
# ------------------------ STEP 1 --------------------------------------------------
# driver1 = webdriver.Firefox()
driver1 = webdriver.Remote(command_executor=executor_url, desired_capabilities=capabilities)
driver1.get('http://google.com/')
url = driver1.command_executor._url
print(driver1.command_executor._url)
print(driver1.session_id)
print(driver1.title)
# Serialize the session id in a file
session_id = driver1.session_id
# ------------------ END OF STEP 1 --------------------------------------------------
# Pass the session id from step 1 to step 2
# ------------------------ STEP 2 --------------------------------------------------
def attach_to_session(executor_url, session_id):
original_execute = WebDriver.execute
def new_command_execute(self, command, params=None):
if command == "newSession":
# Mock the response
return {'success': 0, 'value': None, 'sessionId': session_id}
else:
return original_execute(self, command, params)
# Patch the function before creating the driver object
WebDriver.execute = new_command_execute
temp_driver = webdriver.Remote(command_executor=executor_url)
# Replace the patched function with original function
WebDriver.execute = original_execute
return temp_driver
# read the session id from the file
driver2 = attach_to_session(executor_url, existing_session_id)
driver2.get('http://msn.com/')
print(driver2.command_executor._url)
print(driver2.session_id)
print(driver2.title)
driver2.close()
# ------------------ END OF STEP 2 --------------------------------------------------

After trying most of these solutions, this solution has worked for me the best. Thanks to #Ahmed_Ashour.
For those who are struggling with this problem, here are a few tips to make your life a bit easier:
1- use a driver manager instead of a manually installed driver (to avoid compatibility issues)
from webdriver_manager.chrome import ChromeDriverManager
driver = webdriver.Chrome(ChromeDriverManager().install(),options=chrome_options)
2- Make sure to close the running chrome instance before starting the new one with the debugging port
chrome.exe --remote-debugging-port=9222 --user-data-dir="C:\selenum\ChromeProfile"

This is pretty easy using the JavaScript selenium-webdriver client:
First, make sure you have a WebDriver server running. For example, download ChromeDriver, then run chromedriver --port=9515.
Second, create the driver like this:
var driver = new webdriver.Builder()
.withCapabilities(webdriver.Capabilities.chrome())
.usingServer('http://localhost:9515') // <- this
.build();
Here's a complete example:
var webdriver = require('selenium-webdriver');
var driver = new webdriver.Builder()
.withCapabilities(webdriver.Capabilities.chrome())
.usingServer('http://localhost:9515')
.build();
driver.get('http://www.google.com');
driver.findElement(webdriver.By.name('q')).sendKeys('webdriver');
driver.findElement(webdriver.By.name('btnG')).click();
driver.getTitle().then(function(title) {
console.log(title);
});
driver.quit();

Related

Unable to use scraperapi with selenium

I am trying to use the scraperapi with selenium. It runs fine when I use it with python requests with the following code.
import requests
proxies = {
"http": "http://scraperapi:my_api_key#proxy-server.scraperapi.com:8001",
"https": "http://scraperapi:my_api_key#proxy-server.scraperapi.com:8001"
}
r = requests.get('http://httpbin.org/ip', proxies=proxies, verify=False)
print(r.text)
It returns the proxy IP with the above code.
But it returns my original IP when I try with following code.
from selenium import webdriver
PATH = 'C:\Program Files (x86)\chromedriver.exe'
proxy = "http://api.scraperapi.com?api_key=my_api_key&render=true"
options = webdriver.ChromeOptions()
options.add_argument(f'--proxy-server={proxy}')
driver = webdriver.Chrome(PATH, options=options)
url = 'http://httpbin.org/ip'
driver.get(url)
According to ScraperAPI's own guides, the easiest way seems to be using selenium-wire instead of plain selenium
from seleniumwire import webdriver
API_KEY = 'YOUR_API_KEY'
proxy_options = {
'proxy': {
'http': f'http://scraperapi:{API_KEY}#proxy-server.scraperapi.com:8001',
'no_proxy': 'localhost,127.0.0.1'
}
}
driver = webdriver.Chrome(seleniumwire_options=proxy_options)
driver.get("http://httpbin.org/ip")
https://www.scraperapi.com/quick-start-guides/python-selenium-scraper/

to set MutationObserver, How to inject javascript before page-loading using Selenium

I'm trying to set MutationObserver for observing page mutation while loading.
In order to do that, MutationObserver should be configured before page loading.
With selenium-chromedriver, couldn't find the way to inject JS for such purpose.
I know chrome extension can do that but extensions won't work on headless mode.
That's the problem.
It's possible via the DevTool API by calling Page.addScriptToEvaluateOnNewDocument
from selenium import webdriver
from selenium.webdriver.remote.webdriver import WebDriver
import json
def send(driver, cmd, params={}):
resource = "/session/%s/chromium/send_command_and_get_result" % driver.session_id
url = driver.command_executor._url + resource
body = json.dumps({'cmd': cmd, 'params': params})
response = driver.command_executor._request('POST', url, body)
if response['status']:
raise Exception(response.get('value'))
return response.get('value')
def add_script(driver, script):
send(driver, "Page.addScriptToEvaluateOnNewDocument", {"source": script})
WebDriver.add_script = add_script
# launch Chrome
driver = webdriver.Chrome()
# add a script which will be executed when the page starts loading
driver.add_script("""
if (window.self === window.top) { // if main document
console.log('add script');
}
""")
# load a page
driver.get("https://stackoverflow.com/questions")
We can now use execute_cdp_cmd(cmd, cmd_args) to execute Chrome Devtools Protocol command in Selenium
from selenium import webdriver
driver = webdriver.Chrome()
driver.execute_cdp_cmd(
"Page.addScriptToEvaluateOnNewDocument",
{
"source": """// Your JavaScript here"""
}
)
driver.get("https://stackoverflow.com")
driver.quit()
The argument for "source" is just a string. So you can actually write your script in a .js file (for syntax highlighting) and read it using Python

Page load strategy for Chrome driver (Updated till Selenium v3.12.0)

I'm using Chrome browser for testing WebApp.
Sometimes pages loaded after very long time. I needed to stop downloading or limit their download time.
In FireFox I know about PAGE_LOAD_STRATEGY = "eager".
Is there something similar for chrome?
P.S.: driver.manage().timeouts().pageLoadTimeout() works, but after that any treatment to Webdriver throws TimeOutException.
I need to get the current url of the page after stopping its boot.
ChromeDriver 77.0 (which supports Chrome version 77) now supports eager as pageLoadStrategy.
Resolved issue 1902: Support eager page load strategy [Pri-2]
From the Webdriver specs:
For commands that cause a new document to load, the point at which the command returns is determined by the session’s page loading strategy.
When Page Loading takes too much time and you need to stop downloading additional subresources (images, css, js etc) you can change the pageLoadStrategy through the webdriver.
As of this writing, pageLoadStrategy supports the following values :
normal
This stategy causes Selenium to wait for the full page loading (html content and subresources downloaded and parsed).
eager
This stategy causes Selenium to wait for the DOMContentLoaded event (html content downloaded and parsed only).
none
This strategy causes Selenium to return immediately after the initial page content is fully received (html content downloaded).
By default, when Selenium loads a page, it follows the normal pageLoadStrategy.
Here is the code block to configure pageLoadStrategy() through both an instance of DesiredCapabilities Class and ChromeOptions Class as follows : :
Using DesiredCapabilities Class :
package demo; //replace by your own package name
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.DesiredCapabilities;
public class A_Chrome_DCap_Options {
public static void main(String[] args) {
System.setProperty("webdriver.chrome.driver", "C:\\Utility\\BrowserDrivers\\chromedriver.exe");
DesiredCapabilities dcap = new DesiredCapabilities();
dcap.setCapability("pageLoadStrategy", "normal");
ChromeOptions opt = new ChromeOptions();
opt.merge(dcap);
WebDriver driver = new ChromeDriver(opt);
driver.get("https://www.google.com/");
System.out.println(driver.getTitle());
driver.quit();
}
}
Using ChromeOptions Class :
package demo; //replace by your own package name
import org.openqa.selenium.PageLoadStrategy;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
public class A_Chrome_Options_test {
public static void main(String[] args) {
System.setProperty("webdriver.chrome.driver", "C:\\Utility\\BrowserDrivers\\chromedriver.exe");
ChromeOptions opt = new ChromeOptions();
opt.setPageLoadStrategy(PageLoadStrategy.NORMAL);
WebDriver driver = new ChromeDriver(opt);
driver.get("https://www.google.com/");
System.out.println(driver.getTitle());
driver.quit();
}
}
Note : pageLoadStrategy values normal, eager and none is a requirement as per WebDriver W3C Editor's Draft but pageLoadStrategy value as eager is still a WIP (Work In Progress) within ChromeDriver implementation. You can find a detailed discussion in “Eager” Page Load Strategy workaround for Chromedriver Selenium in Python
References:
WebDriver navigation
WebDriver page load strategies
WhatWG Document readyStateChange / readiness
For Selenium 4 and Python
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.page_load_strategy = 'none'
driver = webdriver.Chrome(options=options)
driver.get("http://www.google.com")
driver.quit()
For more details can be found here https://www.selenium.dev/documentation/webdriver/capabilities/shared/#none
In C#, since PageLoadStrategy.Eager doesn't seem to work for Chrome, I just wrote it myself with a WebDriverWait. Set the PageLoadStrategy to none and then doing this will basically override it:
new WebDriverWait(_driver, TimeSpan.FromSeconds(20))
.Until(d =>
{
var result = ((IJavaScriptExecutor) d).ExecuteScript("return document.readyState");
return result.Equals("interactive") || result.Equals("complete");
});
You just add in your chrome driver as a parameter and the TimeSpan is set to a max of 20 seconds in my case. So it will wait a max of 20 seconds for the page to be interactive or complete
Try using explicit wait . Visit this link. It might be helpful
Try this code as well:
WebDriver driver = new FirefoxDriver();
String startURL = //a starting url;
String currentURL = null;
WebDriverWait wait = new WebDriverWait(driver, 10);
foo(driver,startURL);
/* go to next page */
if(driver.findElement(By.xpath("//*[#id='someID']")).isDisplayed()){
String previousURL = driver.getCurrentUrl();
driver.findElement(By.xpath("//*[#id='someID']")).click();
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
ExpectedCondition e = new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver d) {
return (d.getCurrentUrl() != previousURL);
}
};
wait.until(e);
currentURL = driver.getCurrentUrl();
System.out.println(currentURL);
}
I hope your problem will be resolved using above code

selenium grid connction with autoit not working?

selenium grid connection with auto it not working ?
#daluudaluu/PartialSeleniumGridIntegrationWithAutoItExample.java
Last active a year ago
Embed
Download ZIP
Code Revisions 2 Forks 1
Partial Selenium Grid integration support with tools like AutoIt, Sikuli, etc.
Raw
PartialSeleniumGridIntegrationWithAutoItExample.java
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.*;
import org.openqa.selenium.remote.*;
import java.net.URL;
public class DemoTest {
public WebDriver driver;
public DesiredCapabilities capabilities;
#Before
public void setUp() throws Exception {
capabilities = DesiredCapabilities.firefox();
driver = new RemoteWebDriver(new URL("http://localhost:4444/wd/hub" ), capabilities);
}
#After
public void tearDown() throws Exception {
driver.quit();
}
#Test
public void test() throws Exception {
// Use RemoteWebDriver, grab actual node host info
driver.get("http://www.google.com");
String sessionId = ((RemoteWebDriver) driver).getSessionId().toString();
//grid info extractor from: https://gist.github.com/krmahadevan/1766772
String nodeHost = GridInfoExtracter.getHostNameAndPort("localhost", 4444, sessionId)[0];
System.out.println("Extracted hostname: "+nodeHost);
// Now use node host info to handle running AutoIt on that specific node, assuming all needed files deployed to all nodes
// Case 1 - PSExec.exe from Windows host (that is executing this Selenium code) to Selenium node that is Windows host
//String psexecCmd = "C:\\LocalMachinePathTo\\psexec.exe \\\\%s -u %s -p %s -i C:\\GridNodeMachinePathTo\\autoitCompiledScript.exe";
//Process p = Runtime.getRuntime().exec(String.format(psexecCmd,nodeHost,"jdoe","hisPassword"));
//p.waitFor();
// Case 2 - winexe from *nix host (that is executing this Selenium code) to Selenium node that is Windows host
// Example reference: http://secpod.org/blog/?p=661
//String winexeCmd = "/LocalMachinePathTo/winexe -U domainName/jdoe%hisPassword //"+nodeHost+" C:\\GridNodeMachinePathTo\\autoitCompiledScript.exe";
//Process p = Runtime.getRuntime().exec(winexeCmd);
//p.waitFor();
// Case 3 - have SSH installed on Windows-based Selenium nodes, now just connect to node host via SSH to run a command, i.e. execute AutoIt script binary
// no sample code given for Java, but maybe this gives you ideas on Java SSH connection:
// http://stackoverflow.com/questions/995944/ssh-library-for-java
// Case 4 - if you have implemented a custom web service (XML-RPC/SOAP/REST) for AutoIt that listens for requests/commands
// just connect to it via (Java) HTTP library to "http://"+nodeHost+"/someWebServicePath/someCommand" (via GET or POST)
// details not covered, this is just an example. Most people won't be taking this route due to customization & complexity in
// building the web service first
// Case 5 - using AutoItDriverServer that is also running on Selenium nodes
//DesiredCapabilities autoitCapabilities = new DesiredCapabilities();
//autoitCapabilities.setCapability("browserName", "AutoIt");
//WebDriver autoitDriver = new RemoteWebDriver(new URL("http://"+nodeHost+":4723/wd/hub"), autoitCapabilities);
//autoitDriver.findElement(By.id("133")).click();
//and whatever other AutoItX commands to call that you normally have in the AutoIt script that you compile into binary
//for more ideas on AutoIt commands issued as WebDriver commands with respect to Selenium integration, see:
//https://github.com/daluu/AutoItDriverServer/blob/master/sample-code/SeleniumIntegrationWithAutoItDriver.py
//or if you are old school, and want to do that same approach even with AutoItDriverServer,
// assuming you have first set AutoItScriptExecuteScriptAsCompiledBinary to True in autoit_options.cfg file before starting AutoItDriverServer:
//((JavascriptExecutor) autoitDriver).executeScript("C:\\GridNodeMachinePathTo\\autoitCompiledScript.exe");
// Case for Sikuli integration, using https://github.com/enix12enix/sikuli-remote-control
//RemoteScreen rs = new RemoteScreen(nodeHost);
//rs.setMinSimilarity(0.9);
//rs.click("D://test.png");
}
}

How to run Selenium WebDriver test cases in Chrome

I tried this
WebDriver driver = new ChromeDriver();
But I'm getting the error as
Failed tests: setUp(com.TEST): The path to the driver executable must be set by the webdriver.chrome.driver system property; for more information, see code here . The latest version can be downloaded from this link
How can I make Chrome test the Selenium WebDriver test cases?
You need to download the executable driver from:
ChromeDriver Download
Then use the following before creating the driver object (already shown in the correct order):
System.setProperty("webdriver.chrome.driver", "/path/to/chromedriver");
WebDriver driver = new ChromeDriver();
This was extracted from the most useful guide from the ChromeDriver Documentation.
Download the updated version of the Google Chrome driver from Chrome Driver.
Please read the release note as well here.
If the Chrome browser is updated, then you need to download the new Chrome driver from the above link, because it would be compatible with the new browser version.
public class chrome
{
public static void main(String[] args) {
System.setProperty("webdriver.chrome.driver", "/path/to/chromedriver");
WebDriver driver = new ChromeDriver();
driver.get("http://www.google.com");
}
}
You should download the chromeDriver in a folder, and add this folder in your PATH environment variable.
You'll have to restart your console to make it work.
If you're using Homebrew on a macOS machine, you can use the command:
brew tap homebrew/cask && brew cask install chromedriver
It should work fine after that with no other configuration.
You need to install the Chrome driver. You can install this package using NuGet as shown below:
You can use the below code to run test cases in Chrome using Selenium WebDriver:
import java.io.IOException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class ChromeTest {
/**
* #param args
* #throws InterruptedException
* #throws IOException
*/
public static void main(String[] args) throws InterruptedException, IOException {
// Telling the system where to find the Chrome driver
System.setProperty(
"webdriver.chrome.driver",
"E:/chromedriver_win32/chromedriver.exe");
WebDriver webDriver = new ChromeDriver();
// Open google.com
webDriver.navigate().to("http://www.google.com");
String html = webDriver.getPageSource();
// Printing result here.
System.out.println(html);
webDriver.close();
webDriver.quit();
}
}
Find the latest version of chromedriver here.
Once downloaded, unzip it at the root of your Python installation, e.g., C:/Program Files/Python-3.5, and that's it.
You don't even need to specify the path anywhere and/or add chromedriver to your path or the like.
I just did it on a clean Python installation and that works.
Download the latest version of the Chrome driver and use this code:
System.setProperty("webdriver.chrome.driver", "path of chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.manage().window().maximize();
Thread.sleep(10000);
driver.get("http://stackoverflow.com");
On Ubuntu, you can simply install the chromium-chromedriver package:
apt install chromium-chromedriver
Be aware that this also installs an outdated Selenium version. To install the latest Selenium:
pip install selenium
All the previous answers are correct. Following is the little deep dive into the problem and solution.
The driver constructor in Selenium for example
WebDriver driver = new ChromeDriver();
searches for the driver executable, in this case the Google Chrome driver searches for a Chrome driver executable. In case the service is unable to find the executable, the exception is thrown.
This is where the exception comes from (note the check state method)
/**
*
* #param exeName Name of the executable file to look for in PATH
* #param exeProperty Name of a system property that specifies the path to the executable file
* #param exeDocs The link to the driver documentation page
* #param exeDownload The link to the driver download page
*
* #return The driver executable as a {#link File} object
* #throws IllegalStateException If the executable not found or cannot be executed
*/
protected static File findExecutable(
String exeName,
String exeProperty,
String exeDocs,
String exeDownload) {
String defaultPath = new ExecutableFinder().find(exeName);
String exePath = System.getProperty(exeProperty, defaultPath);
checkState(exePath != null,
"The path to the driver executable must be set by the %s system property;"
+ " for more information, see %s. "
+ "The latest version can be downloaded from %s",
exeProperty, exeDocs, exeDownload);
File exe = new File(exePath);
checkExecutable(exe);
return exe;
}
The following is the check state method which throws the exception:
/**
* Ensures the truth of an expression involving the state of the calling instance, but not
* involving any parameters to the calling method.
*
* <p>See {#link #checkState(boolean, String, Object...)} for details.
*/
public static void checkState(
boolean b,
#Nullable String errorMessageTemplate,
#Nullable Object p1,
#Nullable Object p2,
#Nullable Object p3) {
if (!b) {
throw new IllegalStateException(format(errorMessageTemplate, p1, p2, p3));
}
}
SOLUTION: set the system property before creating driver object as follows.
System.setProperty("webdriver.gecko.driver", "path/to/chromedriver.exe");
WebDriver driver = new ChromeDriver();
The following is the code snippet (for Chrome and Firefox) where the driver service searches for the driver executable:
Chrome:
#Override
protected File findDefaultExecutable() {
return findExecutable("chromedriver", CHROME_DRIVER_EXE_PROPERTY,
"https://github.com/SeleniumHQ/selenium/wiki/ChromeDriver",
"http://chromedriver.storage.googleapis.com/index.html");
}
Firefox:
#Override
protected File findDefaultExecutable() {
return findExecutable(
"geckodriver", GECKO_DRIVER_EXE_PROPERTY,
"https://github.com/mozilla/geckodriver",
"https://github.com/mozilla/geckodriver/releases");
}
where CHROME_DRIVER_EXE_PROPERTY = "webdriver.chrome.driver"
and GECKO_DRIVER_EXE_PROPERTY = "webdriver.gecko.driver"
Similar is the case for other browsers, and the following is the snapshot of the list of the available browser implementation:
To run Selenium WebDriver test cases in Chrome, follow these steps:
First of all, set the property and Chrome driver path:
System.setProperty("webdriver.chrome.driver", "/path/to/chromedriver");
Initialize the Chrome Driver's object:
WebDriver driver = new ChromeDriver();
Pass the URL into the get method of WebDriver:
driver.get("http://www.google.com");
I included the binary into my projects resources directory like so:
src\main\resources\chrome\chromedriver_win32.zip
src\main\resources\chrome\chromedriver_mac64.zip
src\main\resources\chrome\chromedriver_linux64.zip
Code:
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.SystemUtils;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import java.io.*;
import java.nio.file.Files;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public WebDriver getWebDriver() throws IOException {
File tempDir = Files.createTempDirectory("chromedriver").toFile();
tempDir.deleteOnExit();
File chromeDriverExecutable;
final String zipResource;
if (SystemUtils.IS_OS_WINDOWS) {
zipResource = "chromedriver_win32.zip";
} else if (SystemUtils.IS_OS_LINUX) {
zipResource = "chromedriver_linux64.zip";
} else if (SystemUtils.IS_OS_MAC) {
zipResource = "chrome/chromedriver_mac64.zip";
} else {
throw new RuntimeException("Unsuppoerted OS");
}
try (InputStream is = getClass().getResourceAsStream("/chrome/" + zipResource)) {
try (ZipInputStream zis = new ZipInputStream(is)) {
ZipEntry entry;
entry = zis.getNextEntry();
chromeDriverExecutable = new File(tempDir, entry.getName());
chromeDriverExecutable.deleteOnExit();
try (OutputStream out = new FileOutputStream(chromeDriverExecutable)) {
IOUtils.copy(zis, out);
}
}
}
System.setProperty("webdriver.chrome.driver", chromeDriverExecutable.getAbsolutePath());
return new ChromeDriver();
}
Download the EXE file of chromedriver and extract it in the current project location.
Here is the link, where we can download the latest version of chromedriver:
https://sites.google.com/a/chromium.org/chromedriver/
Here is the simple code for the launch browser and navigate to a URL.
System.setProperty("webdriver.chrome.driver", "path of chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get("https://any_url.com");