Python with selenium: rerun on pre-existing browser - python

I'm using Python with Selenium 2.44. When the test fails, I can't just uncomment all the code before the failure when debugging it, because the driver will not be declared for the browser. Therefore, whenever I try fixing something, I always have to open a new browser in the test case. This is rather... slow since I have to login, which adds an additional 30 seconds (not devastating, but annoying). I want to know if there's a way for me to just continue a session, or do something that allows me to start the test midway through (so if I have the webpage open already, I can just immediately start clicking things rather than opening a new browser). Is this possible?
For example, if I had something along the lines of:
driver = webdriver.Firefox()
driver.get("google.com")
driver.find_element_by_xpath("//input[#id='gbqfq']").send_keys("cats" + Keys.RETURN)
This should open Firefox, go to google, and search for cats. Pretend like there's a ton of stuff you have to do before you can actually make it to the google page, though. Now if it were to fail on the search for cats, the only way I would be able to test to see if I fixed the code would be to rerun the test (webdriver.Firefox() would open a new browser). Rather than that, assuming I'd still have google open, I'd like the selenium test to just start off on the previous browser and google page (therefore saying the first step in the code would be the send_keys("cats")). Is this possible?
I think that this was a similar question, but it didn't get checked off as answered: How to resume browser session or use existing browser window with Selenium-Python?
This one also seems similar, only pertaining to Java: How do I rerun Selenium 2.0 (webdriver) tests on the same browser?
Thanks.

Look into pdb: https://docs.python.org/2/library/pdb.html
Placing this in your code will stop the progression of the test as is until you tell it to continue in your shell.
Using your code snippit:
from pdb import set_trace
driver = webdriver.Firefox()
driver.get("google.com")
set_trace()
driver.find_element_by_xpath("//input[#id='gbqfq']").send_keys("cats" + Keys.RETURN)
will stop your execution after getting the url, allow you to tinker, and then continue from where the test left off.
Alternatively, while debugging, you can just remove the driver.quit() statement, wherever it happens to be, which will keep the browser open wherever your assertion failed. But if you're using a framework like Django with the LiveTestServer Client, you won't have access to browse the site further. pdb will allow you to keep the test server active.

Related

Selenium ActionChains key commands enacting key shortcut?

I have a Python program that uses APScheduler and Selenium to automate webscraping. Basically it scrapes a particular website once every hour, and then schedules certain more detailed scrapes to happen at intervals.
The issue is that while I want to start the scraper, and then be free to use my computer for other work, Selenium will then automatically focus on the opened chrome tabs whenever a new scrape is started by APScheduler. Because of this, I am trying to find a way to have the new chrome windows open - but I don't have to focus on them. I've already tried headless and phantomJS, but the site is dynamically generated so these don't really work.
My current solution is to open the new window, minimise it, and then immediately shift back to the old window. To do this I want to perform a keyboard shortcut using ActionChains. I currently have this test code:
driver = webdriver.Chrome(ChromeDriverManager().install())
ActionChains(driver).key_down(Keys.CONTROL)
ActionChains(driver).send_keys(Keys.RIGHT)
ActionChains(driver).key_up(Keys.CONTROL)
Currently this code does nothing however. Is there anyway to fix this? I am using Jupyter Notebook and I am on a mac for reference.
NOTE: this code is being run apart from the main program, I am just using it to test if the script will work.
Try this out. You never .perform() it.
ActionChains(driver).key_down(Keys.CONTROL).send_keys(Keys.RIGHT).key_up(Keys.CONTROL).perform()

Using Winium (+ Selenium) with python only allows me to open the app, but then won't interact with it?

When I try to run any kind of code using winium, it will open the app, but then won't execute any of the code afterwards. It's not as if it throws up an error, it just hangs there and won't move on.
I Am using Python 3.7 on a Windows 10 PC.
I have tried the two 'magic' examples that are listed on the github wiki page for Winium, but even that doesn't work. I am able to use selenium to do automated web testing, so I don't think the selenium module is the issue. I have tried importing the time module and making it sleep for 10 seconds in between lines but this has no effect on the outcome.
from selenium import webdriver
driver = webdriver.Remote(
command_executor='http://localhost:9999',
desired_capabilities={
"debugConnectToRunningApp": 'false',
"app": r"C:/windows/system32/calc.exe"
})
# THIS IS WHERE IT SEEMS TO PAUSE INDEFINITELY
window = driver.find_element_by_class_name('CalcFrame')
view_menu_item = window.find_element_by_id('MenuBar').find_element_by_name('View')
view_menu_item.click()
view_menu_item.find_element_by_name('Scientific').click()
view_menu_item.click()
view_menu_item.find_element_by_name('History').click()
window.find_element_by_id('132').click()
window.find_element_by_id('93').click()
window.find_element_by_id('134').click()
window.find_element_by_id('97').click()
window.find_element_by_id('138').click()
window.find_element_by_id('121').click()
driver.close()
I would expect it to press the corresponding buttons, but it doesn't seem to do anything except open the calculator app.
I think this example is written for an older version of calculator. In Windows 10, the "Scientific" button is under the Menu button.
You'll have to find the menu button, click it, and then look for the element "Scientific" in the list.
Also, the numeric values for your arithmatic case are not correct. Pick up a UI inspector tool (inspect.exe, uispy, etc...) to make sure you are targeting the elements correctly.

Preventing Python webbrowser.open() from dominating screen and preventing other processes. Is it possible to open as minimised?

I am using webbroswer.open() in a loop to download multiple files at given intervals.
The issue I am having is that whenever the browser window opens, it becomes the primary window and thereby interrupts and disrupts my ability to use the computer. Downloading multiple files means this can last some time. The broswer continuously flashing open is obviously jarring.
Is there any way to instruct webbrowser to open the browser minimised by default or otherwise avoid this issue in some other ingenious way?
Much appreciated!
If you are open to using other modules I would urge you to look into selenium. This allows you to do many things, and one of them is to launch in headless mode (so as not to disturb you as it loads pages). The documentation is at:
https://selenium-python.readthedocs.io/
And you would be interested in the headless option
You would be advised though to make sure your script works without this enabled before you enable it though.
Sample code:
import selenium
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
my_options = Options()
my_options.headless = True # set to False for debugging!!
browser = webdriver.Chrome(options=my_options)
browser.get('http://www.google.com')
print('Done.')
You will need to download the proper drivers (just follow the instructions on the link I posted) for whatever browser you'd like. I picked Chrome, but they have Edge, Firefox, and Safari browsers as well!

Questions regarding Splinter for file download

I have written a simple program to mimic logging into a web page, clicking on a few options and the final step is to click on a link to generate a report. Everything seems to be running fine on my PC and the report actually get downloaded into the default download directory(I am using Chrome). However, when my colleague tried it, the file download was cut off and the browser process terminates itself running the same code and I can't seem to replicate what he saw.
My code looks like this:
browser = splinter.Browser('chrome')
browser.visit('https://village-us.albourne.com/castle/')
browser.fill('username','xxx')
browser.fill('password','xxxxx')
browser.find_by_name('signinform')
button = browser.find_by_name('submit_0')
button.click()
browser.visit('https://village-us.albourne.com/castle/hf/listingoptions')
rptButton = browser.find_by_name('buildReport')
rptButton.click()
browser.find_by_name('checkbox_0').click()
browser.find_by_name('checkbox_1').click()
excelButton = browser.find_by_id('excelReport').first
excelButton.click()
So my questions are:
1. Is the excelButton.click() response supposed to be synchronized to the browser's response(per default timeout of course)?
2. Is there a way to change the default timeout period?
3. Since the browser is getting opened, if we run this process as a batch process, will this pose any issue when the screen lock is on? I have read about using the zope-testbrowser which seems like a good alternative for this purpose, but not sure if zope-testbrowser supports file downloads as well.

How to test jquery ajax tabs with selenium?

I'm testing a django app with selenium, and one of my pages uses the jquery ui tabs element. One of the tabs contains a simple table listing some users, and is loaded via ajax. When using the app, the tab works just fine, but when automating the test with selenium, the tab doesn't appear to load it's content!
I'm writing the tests myself in python. At first, I was using the click method of selenium RC, but as I -painfully- learned from a previous test, that is rather buggy when it comes to anchor tags, so I resorted to the solution I used before: the wait_for_condition method and explicitly called the tab click event (and even the load event!) and nevertheless the tab was still not working!
I'm in despair here, the majority of my tests depend on that page and almost half of them are on that table, but, alas, it seems selenium is screwing up the javascript!
(I have other tests in the class, and they run just fine, so nothing weird is going on at the server level, it seems to be a problem caused by selenium in the client side)
My test code is similar to this:
class TestMyApp(TransactionTestCase):
urls = 'myapp.test_urls'
def setUp(self):
self.verificationErrors = []
self.selenium = selenium("localhost", 4444, "*chrome", "http://localhost:8000/")
self.selenium.start()
#self.selenium.set_speed(2000)
self.selenium.window_maximize()
def test_users_list(self):
"""Test that an app's users are correctly listed"""
sel = self.selenium
users = []
for u in range(settings.FREE_USER_LIMIT/2):
users.append(self.app.users.create(name="testUser_%s"%uuid4()))
sel.open("/")
sel.wait_for_page_to_load("30000")
sel.wait_for_condition('selenium.browserbot.getCurrentWindow().jQuery("#tabs").tabs("select",1);\
selenium.browserbot.getCurrentWindow().jQuery("#tabs").tabs("load",1);',
3000)
for user in users:
try: self.failUnless(sel.is_text_present(user.name))
except AssertionError, e: self.verificationErrors.append(str(e))
try: self.failUnless(sel.is_text_present(str(user.added.date())))
except AssertionError, e: self.verificationErrors.append(str(e))
def tearDown(self):
self.selenium.stop()
self.assertEqual([], self.verificationErrors)
This could be a few things. It could be that Selenium is having trouble clicking the anchor but I actually haven't heard of that trouble and it sounds less likely. It sounds like the click() method returns OK, it doesn't give you "element not found", right? When you do the click the jquery tab javascript just isn't doing what's expected. In my experience this usually comes down to the same issue -- since Selenium executes very quickly, when javascript is rendering portions of the page and effecting the DOM continuously sometimes when Selenium goes to interact with dynamically generated parts of the page (say to click this tab), the piece it's interacting with depends on some other piece that actually hasn't fully loaded yet. It's probably microseconds away from fully loading in fact, but selenium is too fast. You already understand this of course, you have the right idea with the wait_for condition looking for the tabs to be loaded. My guess would be it's probably just not long enough. You have to find some evaluation to make that says the whole UI tabs thing is loaded and rendered. Does the tabs API have some callbacks you can add to set a "done loading" variable or does it expose a variable like that? Barring figuring out what the proper expression is to find the point in time when the UI tabs are actually ready to be clicked, which possibly could be tricky, you can resort to outright pauses to make sure the part of the page is ready to go before you interact with it. I see no problem in sleep(2), or even sleep(5), etc. in the code if it's necessary to get it to work. One way you can test that this is really what's going on is by firing up the scenario in the interactive interpreter (gotta love Python, beats the pants off of doing this in Java). Paste the code in line by line to get to the trouble point, or comment out the selenium.stop() call in your teardown method and any test code after the trouble point, so it leaves the selenium window open and exits. Then instantiate a selenium object in the interactive interpretter and hijack the open session:
selenium = selenium("localhost", 4444, "*chrome", "http://localhost:8000/")
selenium.sessionId = "0asdd234234023424foo" #Get this from the Se window
...to get interactive control of the window. Then you can see about making the selenium.click() or make selenium.get_eval('...js...') calls to investigate the javascript landscape at that point in time. My guess is when you do this, the click() will actually work fine when you type it in, because by the time you get the session loaded and get around to typing in selenium.click('blah_tab_locator'), the tab guts will all be loaded and ready to go. It's just that when Python is making the calls it does it way too fast for the browser when there are these dynamic renderings going on. If the click works fine when you do it manually through selenium like this, then you know it's a timing issue. Find that proper wait_for_condition or condescend to a python sleep(). Otherwise, if the click continues to not work when you do this, then it's probably a problem with the locator being used. The tab UI has a click or a mouseup or a focus or some kind of event handler on some part of the tab structure, maybe it's just about finding the right part of the tab to click or the right event to fire. If it isn't that then it perhaps could be as you mention some kind of strange interaction between Selenium and Jquery UI, but that would surprise me and I'd be curious to know. Poke around with get_eval() to see what's going on in the javascript if so. It sounds like a timing issue to me though.

Categories

Resources