Changing execution speed of tests? - python

Updating with more context: Selenium 1 had a command called "setSpeed." This allowed the execution of each command to be slowed down by X milliseconds. The team behind Selenium 2 (Webdriver) decided to deprecate this command and now there is no way to slow down the tests to run at speeds where it's easy to visually monitor the App during execution. I've read the developers' explanation as to why they deprecated it, as well as the suggested workarounds like using implicit_waits, but that doesn't solve the issue for me (or the other people complaining about the deprecation). That said, I was hoping to work around this by setting a global execution speed that would be applicable to either each method in unittest, or the entire suite of tests.
Original Question: I have different unit tests that I'd like to execute using different delays between commands. I know that I can keep copying and pasting time.sleep between the commands, but surely there is a way to just set a universal sleep that will be run before each command in the specified method?
def test_x_test(self):
driver = self.driver
time.sleep(2)
print("running the First selenium command such as click button")
time.sleep(2)
print("running another Selenium command such as click link ")
time.sleep(2)
self.driver.quit()
if __name__ == '__main__':
unittest.main()

Ahh now the answer is so obvious.
Create a helper method that controls webdriver actions and before it executes the action put in a pause:
The below is going to be pseudocode-ish as I no longer have access to a Python IDE at work
#passing in Webdriver instance and the command we want to execute into our helper method
webdriverHelper(driver, command):
#this 2 second sleep will get run each time
time.sleep(2)
if command == "click":
driver.getElement.click()
elif command== "getText":
driver.getElement.getText()
etc...............

Related

Python selenium share second browser between test

I'm quite new to selenium and may be doing something wrong. Please fix me!
I'm creating some E2E tests, part of them require second account.
Each time I open new browser, I have to make login procedure, that takes time.
So, I decided to keep the second browser open between tests and reuse it.
But I can't pass the newly created selenium object to the second test. What I'm doing wrong?
class RunTest(unittest.TestCase):
#classmethod
def setUpClass(self):
#main browser that I always use
self.driver = webdriver.Chrome(...)
def init_second_driver(self):
#second browser that could be used by some tests
self.second_driver = webdriver.Chrome(...)
def test_case1(self):
if not self.second_driver:
self.init_second_driver()
#some tests for case 1
def test_case2(self):
if not self.second_driver: #this check always fails! WHY?
self.init_second_driver()
#some tests for case 2
Thank you in advance
Everytime you create your chromedriver object it's default option is to create a new Chrome profile. Think of a profile as your local cookie store and chache.
You want this to happen. Selenium is designed for testing and logging in each time without history ensures you tests always start from the same state (not logged in and no cookies).
If you have a lot of tests and want your suite to run faster consider running tests in parallel.
For now, if you want to try sharing state between tests (i.e. staying logged in) you can instruct chrome to reuse a profile with the following option/tag:
options = webdriver.ChromeOptions()
options.add_argument('--user-data-dir=C:/Path/To/Your/Testing/User Data')
driver = webdriver.Chrome(options=options)
That should remove the need for a second browser your state.

How to program a daily task with Python & Selenium

I have to run a daily web search with selenium, so I made a Selenium function and put it in a infinite while loop using the time module:
while True:
selenium_function()
time.sleep(86400)
Is this the right way to do it? Or should I use instead an inner Selenium option ?
EDIT
I found (while looking for cron on YouTube...) this Python module scheduler, so my code is now like that:
schedule.every().day.at("10:30").do(selenium_function)
while True:
schedule.run_pending()
time.sleep(1)
Do you have any experience with this way?

Selenium browser instance can be accessible from a different process?

What I am currently trying to do is the following. There are a number of changing values (js driven) in a website that I am monitoring and saving to a database using Selenium. The values are read through infinite loops, from elements found with selenium's find_element.
This works as intended with one process. However, when I try to multiprocess this (to monitor multiple values at the same time), there seems to be no way to do it without opening one separate browser for each process (unfeasible, since we are talking about close to 60 different elements).
The browser I open before multiprocessing seems to not be available from within the various processes. Even if I find the elements before the multiprocessing step, I cannot pass them to the process since the webelements can't be pickled.
Am I doing something wrong, is selenium not the tool for the job, or is there another way?
The code below doesn't actually work, it's just meant to show the structure of what I currently have as a "working version". What I need to get away from is opening the browser from within the function and have all my processes relying on a single browser.
import time
import datetime
import os
from selenium import webdriver
from multiprocessing import Pool
def sampling(value_ID):
dir = os.path.dirname(__file__)
driver = webdriver.Firefox(dir)
driver.get("https:\\website.org")
monitored_value = driver.find_element_by_xpath('value_ID')
while(1):
print(monitored_value.text)
time.sleep(0.1)
value_array = [1,2,3,4,5,6]
if __name__ == '__main__':
with Pool(6) as p:
p.map(getSampleRT, value_array)
You can checkout selenium abstract listeners if you want to capture the changes in elements. By implementing a listener you can get rid of infinite loops. Here is an example that i think it can work for you.
class EventListeners(AbstractEventListener):
def before_change_value_of(self, element, driver):
# check if this is the element you are looking for
# do your stuff
print("element changed!")
driver_with_listeners = EventFiringWebDriver(driver, EventListeners()
# wait as much as you like while your listeners are working
driver_with_listeners.implicitly_wait(20000)
Also you can checkout this post for more complete implementation.

Getting stuck executing infinite javascript loop in Python's Selenium chromedriver

I am trying to build a service where users can insert their Javascript code and it gets executed on a website of their choice. I use webdriver from python's selenium lib and chromedriver. The problem is that the python script gets stuck if user submits Javascript code with infinite loop.
The python script needs to process many tasks like: go to a website and execute some Javascript code. So, I can't afford to let it get stuck. Infinite loop in Javascript is known to cause a browser to freeze. But isn't there some way to set a timeout for webdriver's execute_script method? I would like to get back to python after a timeout and continue to run code after the execute_script command. Is this possible?
from selenium import webdriver
chromedriver = "C:\chromedriver\chromedriver.exe"
driver = webdriver.Chrome(chromedriver)
driver.get("http://www.bulletproofpasswords.org/") # Or any other website
driver.execute_script("while (1); // Javascript infinite loop causing freeze")
You could set a timeout for your driver.execute_script("while (1);") call.
I have found another post that could solve this issue.
Basically, if you are on a Unix system, you could use signal to set a timeout for your driver.execute_script("while (1); call.
Or if you could run it in a separate process and then end the process if it takes too long using multiprocessing.Process. I'm including the example that was given in the other post:
import multiprocessing
import time
# bar
def bar():
for i in range(100):
print "Tick"
time.sleep(1)
if __name__ == '__main__':
# Start bar as a process
p = multiprocessing.Process(target=bar)
p.start()
# Wait for 10 seconds or until process finishes
p.join(10)
# If thread is still active
if p.is_alive():
print "running... let's kill it..."
# Terminate
p.terminate()
p.join()

How to Speed up Test Execution Using Selenium Grid on single machine

I am selenium python and I would like to speed up my tests. let's say 5 tests simultaneously. How can I achieve that on the single machine with the help of selenium grid
You won't need a Selenium Grid for this. The Grid is used to distribute the test execution across multiple machines. Since you're only using one machine you don't need to use it.
You are running tests so I'm assuming you are using a test framework. You should do some research on how you can run tests in parallel using this framework.
There will probably also be a way to execute a function before test execution. In this function you can start the driver.
I'd be happy to give you a more detailed answer but your question is lacking the framework you are using to run the tests.
This is my base class:
class BaseTestCase(object):
_multiprocess_can_split_ = True
def setUp(self):
self.driver = webdriver.Firefox()
self.driver.get("https://login.com")
self.assertEqual("Authorization required", self.driver.title)
def tearDown(self):
if sys.exc_info()[0]:
test_method_name = self._testMethodName
self.driver.save_screenshot("users/desktop/ErrorScreenshots/" + test_method_name + ".png")
self.driver.quit()
When I try to achieve this with nose by typing nosetests --processes=2 in terminal. it opens all 30 browsers at the same time and all test fails

Categories