Repository navigation
Closed
Description
What do you guys think about this kind of enhancement:
Add a new KW (or extend the Create Webdriver) for attaching to an existing browser/selenium session.
This doesn't make that much sense in "production" environment but would be very useful when implementing test cases. The idea would be to speed-up following scenarios
- When testing web apps there's quite often a scenario where you do lots of stuff and then something breaks: e.g. you have typo in your xpath, a timing issue with (e.g. jQuery not finished) or something else. When this happens you have to start from the beginning but it would be great if you could continue from the point where the TC broke ...
- In environments where the set-up is time consuming, it would great to reuse the browser session(s). For example a set-up where you open a browser and login to the web-app, open another browser and login to the CRM, open yet another browser and login to a web-email app. It would be great to keep those 3 browsers open and skip the browser opening and login steps...
I need this functionality and will implement it for sure, the question is just: should I implement it in my libraries (that use selenium2lib) or should I create a PR for this?
Here a short example how to connect to an existing session:
- Open new browser, print out the session details and leave the browser open
> python sel.py
c1c31e1e-9b19-4363-9ab7-369e84313601 http://127.0.0.1:55486/hub
- Go manually to google.com with the browser
- re-attach (with session details) and click the I'm feeling lucky button:
> python sel.py c1c31e1e-9b19-4363-9ab7-369e84313601 http://127.0.0.1:55486/hub
sel.py file:
from selenium.webdriver import Firefox, Remote
import sys
def open():
driver = Firefox()
print("%s %s" % (driver.session_id, driver.command_executor._url))
def attach(sid, url):
driver = Remote(command_executor=url, desired_capabilities={})
driver.session_id = sid
driver.find_element_by_xpath("//input[contains(@value, 'Lucky')]").click()
sid = sys.argv[1] if len(sys.argv) > 1 else None
url = sys.argv[2] if len(sys.argv) > 2 else None
if sid is None:
open()
else:
attach(sid, url)
Reacted by Marcelo D Montu and Hassan Akram
Activity
pekkaklarck commentedon Nov 18, 2016
AFAIK this isn't supported by Selenium itself.
aaltat commentedon Nov 18, 2016
Pekka is right and your request is not possible: SeleniumHQ/selenium-google-code-issue-archive#18 If you want support for this, then could you open issue to the selenium side.
Because this is not an issue Selenium2Library or we can not do anything to fix it, I am closing the issue.
As a side note, if your test setup time is too big, which is also my problem, it's usually best idea to start changing the product to the direction that it can be tested in smaller chunks.
yahman72 commentedon Nov 18, 2016
First of all, my example code does exactly this, it reuses the Firefox session = not possible is definitely not correct.
About that selenium issue:
Assuming the worst-case, i.e. works only with Firefox, this functionality would be usable because you could do (most of) the test case implementation with Firefox to get rid of those coding errors...
hirsivaja commentedon Nov 18, 2016
I think they are talking about a different issue in the Selenium Github page. They are saying that it is impossible to attach the webdriver to an existing browser instance that is started without Selenium. Yahman on the other hand is suggesting that Selenium2Library should be able to connect to a running webdriver instance instead of creating a new one and possibly switching between instances during the test case.
pekkaklarck commentedon Nov 18, 2016
Sorry, didn't read the issue fully when I see this on mobile. What Selenium cannot do is attaching to an already externally opened session, but you apparently want to attach to a session that Selenium itself has already opened.
pekkaklarck commentedon Nov 18, 2016
Could you clarify how would you use this functionality in practice? You one test run leave a browser open and you'd run a separate that attaches to that?
Would you be interested to implement this support yourself?
yahman72 commentedon Nov 18, 2016
@pekkaklarck: Correct, open browser with Selenium and reconnect (see/try the example code). Just read the original issue description - without using your mobile :-)
As I already mentioned: I'll definitely implement this for myself. For me it's enough when it works with Firefox only, but if the same implementation works also for the other browsers even better.
I propose the following:
pekkaklarck commentedon Nov 18, 2016
At least I don't see any problems adding this kind of functionality, but it definitely need to support also other browsers than Firefox. If it isn't a generic Selenium feature, there's a big chance future changes to Firefox break it. If it's part of the Selenium spec, then the feature ought to be stable.
Part of the implementation would be figuring out how to get the session id so that it can be used later. Perhaps there could be a separate
Save Session Idkeyword that saves the id into a temporary file thatAttach To Browsercould then automatically read.ombre42 commentedon Nov 18, 2016
I have been in your situation, dealing with tests that fail after minutes of execution, so I understand why you might want this. My question to you is - have you tried using a debugger to handle these scenarios?
I have done the very crude step of inserting a line like this in a test:
But you have to do everything on the command line in pure python.
There is also robotframework-debuglibrary. I have not tried it but it looks pretty awesome.
The problem with attaching to a existing session include:
aaltat commentedon Nov 19, 2016
I also know this pain, specially when developing the test. To the problems that @ombre42 did say and which I also know, I have one more thing to consider. The internal state of the SUT.
Usually when user logs in to the web app, there is a state. Example when testing that user account is locked after X number of failure login attempts, there is internal counter in the SUT which I need to take in to the consideration. Because if that internal state is not cleared, the SUT will behave differently than expected in the second test run (when those setup functionality is not executed to clear/reset the SUT) and test will fail again but from a different reason.
To tackle the problem, I try to develop the test in smaller pieces. Do the setup once (like a swing deployment, user creation and so on) and then develop the first thing and then jump directly to the next. Like in this case open browser to the login page and enter wrong password. Iterate over until that part works fine. Then check the error message is displayed correctly. Then repeat the keywords few times that the account is locked. Then stay I stay in this state (I don't run the keywords which will lock the account, I trust that application keeps the account locked) and develop keywords to verify that account is locked.
But each web app is different and what others are doing may not be suitable for you. And the solution which you are proposing may be the best for you.
Other idea which comes in to my mind, is to create a keyword in S2L which allows users to register driver to the S2L. It would give users more freedom to create the driver as users wanted and still benefit from the S2L functionality. There is internal interface, but it's not exposed as a keyword.
yahman72 commentedon Nov 21, 2016
Thanks for the tips. That debuglibrary looks interesting, it looks like that it could be useful for some scenarios. However my main issue is not how to figure out what went wrong (RF debug logs have been good enough for this purpose) but the complexity of the test environment.
I'm doing end-to-end testing for a set of systems, i.e. interactions between the systems e.g. "do something in WebApp-A, check WebApp-B and do something, check WebApp-A and WebApp-C, etc.". In another words, I have 3-4 Browser Windows that open at each pybot-execution, only opening those windows takes forever (at least feels like it :-). This is one the steps that I'm trying to speed up with this.
aaltat commentedon Nov 21, 2016
As a side note one can get the session ID from the server side: https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol#sessions
You may need to build some logic, if there are multiple session ID lying around in the server side.
yahman72 commentedon Nov 21, 2016
As promised, here my findings:
WebDriver differences (when re-attaching to a session using that
webdriver.Remote(desired_capabilites={})from the example code:The new window is opened, because the
webdriver.Remote()'s__init__callsstart_session()that sends a POST to http://localhost/hub/session with thatdesired_capabilities={}. Firefox seems to be the only browser that does not open a new window when this happens.This is of course not good, i.e. we should avoid calling that
start_session()because we don't want create a new session. Instead we'd need something likeReusableWebDriverthat inherits from thewebdriver.Remotebut doesn't create a new session - and this is where it gets a bit ugly:webdriver.Remote()'s__init__you'd need to copy-paste it to yourReusableWebDriver__init__and comment out thestart_session()stepwebdriver.Remote()'s__init__hasn't changed in the past years but if it does you'd need to do that copy-paste exercise again.However, I made a quick-and-dirty implementation of this:
ReusableWebDriverthat skips the session creation stepsCreate WebdriverKW now stores the session info (session ID, command executor URL and capabilities) into a fileCreate WebdriverKW withRemoteargument theReusableWebDriveris created using the session info from the file.The code is in my fork i.e. https://github.com/yahman72/Selenium2Library/tree/reusable_session
This seems to work with the browsers I have installed (FF, Chrome and IE), and I don't see any reason why it shouldn't work with all other browsers and the grid. There are, of course, some limitations e.g. with the runtime variables (as @ombre42 mentioned) that might not be "correct" on the re-execution. Thee kind of things aren't, IMHO, selenium2library's problem, but more a test-implementation planning topic that could be solved by organizing the Test development differently (like @aaltat wrote above)
And now the big question:
Is it worth implementing this for the selenium2library? That copy-paste exercise is pretty ugly...
If I would implement this properly I'd probably do it like @pekkaklarck already proposed i.e.:
This way there would not be any changes in the existing code.
7 remaining items
aaltat commentedon Dec 10, 2016
@yahman72 sorry that it takes so long to review this pull request but the release 2.0 takes lot of attention.
aaltat commentedon Feb 8, 2017
@yahman72 did you actually create a PR?
axelPalmerin commentedon Mar 28, 2017
This is my solution:
https://github.com/axelPalmerin/personal/blob/master/webdriver.py
2. Replace on remote dir:
/usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/
3.Run hub and node:
$ java -jar selenium-server-standalone-3.3.1.jar -role hub
$ java -jar selenium-server-standalone-3.3.1.jar -role node
yahman72 commentedon Mar 29, 2017
@aaltat sorry, missed your comment about the PR.
No I did not, because my expectation was that we'll have some discussions about the implementation before I finalize and submit the PR. This was not so good as this topic was now idle for some and we almost forgot it :-)
I submitted the PR #783 - we can continue the discussion based on that. It probably needs some updates since it was forked some time ago...
aaltat commentedon Mar 29, 2017
I was trying to read your code, but because it was in multiple commits is was difficult. In PR, it's easier to have a good understanding what is changed in overall.
yahman72 commentedon Mar 30, 2017
True - just check the PR and let me know if there's something unclear.
vishalekhe commentedon Aug 4, 2017
I have used modified webdriver.py and it worked for me.
We use robot.run() function to start the automation tests. With mentioned solution, I need to get manually the session id & url i.e. command_executor with some program and then feed it to webdriver.py. If browser closes I need to it often.
Is there a way to pass session id and command_executor to robot.run() which will take care passing session id and command_executor to webdriver.py.
sheikhsamina commentedon Sep 25, 2018
String userProfile= "C:\Users\user\AppData\Local\Google\Chrome\User Data\Default\";
System.setProperty("webdriver.chrome.driver","C:\Users\user\Desktop\chromedriver.exe");
ChromeOptions options = new ChromeOptions();
options.addArguments("user-data-dir="+userProfile);
options.addArguments("--start-maximized");
WebDriver driver = new ChromeDriver(options);
driver.get("http://www.google.com");
The above code is working for me to save cookies and history using selenium web driver
aaltat commentedon May 21, 2019
Closing due inactivity.
zeeshanyshaikh commentedon Aug 31, 2020
ortizjeison commentedon Oct 21, 2023
Hi everyone , any news about this initiative?
emanlove commentedon Oct 21, 2023
@ortizjeison Jeison, it is not on our radar. I'll note much of the discussion around this was before Tatu released the SeleniumLibrary plug-in API and the extending capabilities. One may be able to connect through those extension options but I really have not explore that idea. I'm hesitant to give much indication that this will became a priority or a keyword would be added. So one could explore this more but I caution about devoting too much resources if it requires some changes within the core library.