Suppose you are running a long Selenium test. The test runs fine but fails towards the end as some element was not found or was not clickable. Ideally, you would like to fix the locator and check it immediately. Now you wonder if you can reuse your browser session from the same point where the failure occurred. This post shows you how to do just that! This would help you to debug the locators used quickly, instead of running your whole test again.
Extract session_id and _url from driver object
We are taking advantage of the fact that Selenium lets you attach a driver to a session id and an URL. You can extract your session id and _url from the driver object as mentioned below
session_url = driver.command_executor._url session_id = driver.session_id |
Tie it up with your framework
In case you are using a framework, you can print out the session id and url in the method where you try to get the element. In an example shown below, I am using a get_element method which would return the DOM element. I am printing the session id and url whenever the find_element method fails
def get_element(self,xpath): "Return the DOM element of the xpath or 'None' if the element is not found " dom_element = None try: dom_element = self.driver.find_element(xpath) except Exception,e: self.write(str(e),'debug') self.write("Check your locator-'%s"%xpath) #Print the session_id and _url in case the element is not found self.write("In case you want to reuse session, the session_id and _url for current browser session are: %s,%s"%(driver.session_id ,driver.command_executor._url)) return dom_element |
Use the session id and url
Now you can use the session id and url, in order to debug the locators. Open python command line tool and use the below code
from selenium import webdriver #Pass the session_url you extracted driver = webdriver.Remote(command_executor=session_url,desired_capabilities={}) #Attach to the session id you extracted driver.session_id = session_id #Resume from that browser state elm = driver.find_element_by_xpath("xpath") elm.click() #Perform required action |
Note1: Currently I am able to reuse the session extracted only from Chrome browser. For Firefox there are some Issue. Link 1 and Link 2
Note2: This code is present in our open-sourced Python-Selenium test automation framework based on the page object pattern. We strongly recommend you check it out!
If you are a startup finding it hard to hire technical QA engineers, learn more about Qxf2 Services.
I am a dedicated quality assurance professional with a true passion for ensuring product quality and driving efficient testing processes. Throughout my career, I have gained extensive expertise in various testing domains, showcasing my versatility in testing diverse applications such as CRM, Web, Mobile, Database, and Machine Learning-based applications. What sets me apart is my ability to develop robust test scripts, ensure comprehensive test coverage, and efficiently report defects. With experience in managing teams and leading testing-related activities, I foster collaboration and drive efficiency within projects. Proficient in tools like Selenium, Appium, Mechanize, Requests, Postman, Runscope, Gatling, Locust, Jenkins, CircleCI, Docker, and Grafana, I stay up-to-date with the latest advancements in the field to deliver exceptional software products. Outside of work, I find joy and inspiration in sports, maintaining a balanced lifestyle.
Thank you for this!
In my case the webdriver.remote opens a new completely empty window above the existent one.
It’s circumvented by sendKeys Alt+F4 and/or AppActivate(“Google Chrome”)
Those functions can be found in win32com.client
I too observed the empty window opening up. Thanks for letting me know how to find a way around it.
Actually, to fix this annoying empty window issue, you should just close browser before you re-set session_id for it:
cls.browser = webdriver.Remote(command_executor=session_url, desired_capabilities={})
cls.browser.close()
cls.browser.session_id = session_id
Is this possible to acheive using java code.
Yes, it’s possible to achieve using java code. The following link may help you to achieve it https://stackoverflow.com/questions/18212389/maintain-and-re-use-existing-webdriver-browser-instance-java
Any sample code written in Ruby for the same usecase?
Hi Vishwanath,
We do not have code support in Ruby at the moment. You can refer to Rahul Bhave’s reply to your previous comment for hints.
Regards,
Akkul
Hi, the code no longer works.
I am using selenium 3.9.0 with python, your code ever open new browser.
I tested with chromedriver and geckodriver(firefox).
Please, inform version of your selenium
Hi Jhony,
Can you let me know what error you get when you try out the code?. Yes, the code opens a new browser session and you can try the suggestions in some of the above comments to fix that issue. My selenium version is 3.6.0
Because of the version compactability between your selenium and firefox driver it will not work. Try o downgrade your firefox driver
the best way to void create a emtpy windows is mock start_session(), the code below:
def start_session(self, *args):
”’ mock method, to void create a emtpy chrome page ”’
pass
def reuse_driver(url, session_id):
webdriver.Remote.start_session = start_session # user mocked method, do nothing
driver = webdriver.Remote(command_executor=url)
driver.session_id = session_id
driver.w3c = None
return driver
Has anyone tried this when running Selenium on Browserstack?…
When launching the new driver, it seems it’s not possible to change the session id. (driver.session_id = session_id ) So the browserstack session gets stuck.
Any tips or advice would be really helpful…
Gilles Vanermen , we haven’t tried this with browserstack . But this was meant to help debugging tests on local system to save time
If the browser session was opened by some other application and we want to perform automation on that browser session, then is it possible?
Hi John,
We need session_id and Session_url to do this. I don’t know of a way to get this for an already opened session by some other application
Was looking for this particular implementation of reusing the browser, but not found in your framework, where is it ?
Hi,
The posts only gives an example on how you can use session id and url in the framework. In this example we are printing the session id and url whenever the find_element method fails. You can print out the session details in the method where you try to get the element.
I hope this information helps !!!
Hi nice information,
Am I right about this:( in my understanding) your code is that you run fistly run it via python so because of that, you can get the ID of
session_url = driver.command_executor._url
session_id = driver.session_id
but how to use already opened selenium(manual opening or already open by other python script that already stop). Let say we have opened 3 window selenium. How to get the list the session ID of that three ‘session_url’ and ‘session_id’ and so we can control the right one which opened the url https://google.com.
Hi,
You could use get.windowshandles() to store all the session ids of the open windows. You could also print store the session_id as soon as the window is spawned.
I would suggest using a similar code:
I am using SeleniumBasic with VBA for Microsoft Access and have asked this question and can’t get an answer anywhere:
Can someone please help me reconnect in vba to an existing selenium webdrover session. I figured out how to get the sessionID, the driver IP and the driverInfo but can’t quite figure out the VBA syntax.
Thanks,
Andrew
Hi Andrew,
we majorly use Python with Selenium and the blog details about reusing the browser session with Python. We are unable to extend support in VBA – SeleniumBasic which is your case. You could refer to,
https://tarunlalwani.com/post/reusing-existing-browser-session-selenium-csharp/ and see if you could implement the logic in your language base.
Hi,
I have a problem. I search to reuse driver (webdriver) for keep the same instance of my browser and not reopen an other browser. In my script, the driver is undefined in my function test.
Help me please if someone have a solution.
My code with nodeJS (in javascript):
var express = require(‘express’);
var app = express();
var ip = “localhost”
var port = 80;
var server = require(“http”).createServer(app);
var io = require(‘socket.io’)(server);
var webdriver = require(“selenium-webdriver”);
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(‘/’, express.static(__dirname + ‘/’ + application));
server.listen(port, function() {
var driver = new webdriver.Builder().forBrowser(‘firefox’).build();
driver.get(“http://www.google.com”); //it’s ok
});
io.sockets.on(‘connection’, function(socket) {
//call of test function with socket io
socket.on(“test”, function(data) {
driver.get(“http://www.test.com”); //it’s ko => driver is undefined
});
});
Hi Jeremy,
By reading the script I understood that you have been using Firefox browser. As we have mentioned in our blog to reuse existing selenium browser session works only for Chrome browser. Please refer to the attached link in the blog.
Does anyone have similar implementation in Ruby?
Hi Vishwanath,
There is no direct ruby script available for the similar implementation. However below getting started document has some examples related to ruby.
https://www.browserstack.com/docs/automate/selenium/getting-started/ruby#prerequisites
In case your are specifically looking to retrieve session id then following document will be helpful:
https://www.browserstack.com/docs/automate/selenium/get-session-id#ruby
As per above document the session id can be retrieved in ruby as well using,`driver.session_id`.
You can try the same in your ruby script and proceed with test script.
There is similar java example available in case you want to have a look at it:
https://stackoverflow.com/questions/18212389/maintain-and-re-use-existing-webdriver-browser-instance-java
Regards,
Rahul
Thanks for the reply, I found a way to get this solved using monkey patching
class RemoteWebDriver < Selenium::WebDriver::Driver
def initialize(bridge)
@bridge = bridge
end
end
class RemoteBridge < Selenium::WebDriver::Remote::Bridge
def self.handshake(**opts)
capabilities = opts.delete(:desired_capabilities) { Capabilities.new }
@session_id = opts.delete(:session_id)
Selenium::WebDriver::Remote::W3C::Bridge.new(capabilities, @session_id, **opts)
end
end
caps = Selenium::WebDriver::Remote::Capabilities.firefox()
remote_bridge = RemoteBridge.handshake(url: , desired_capabilities: caps, session_id: )
remote_web_driver = RemoteWebDriver.new(remote_bridge)