How to change self.driver.get() to only self.get() in class? - python

I've been looking for an answer but cant find one
Let's say I have this,
self.driver = webdriver.Chrome(options=self.options)
and then I use,
self.driver.get('http://www.google.com/')
Is there a way for me to use just 'self.' on the next method where everything from self.driver pops up? Like so,
self.get('http://www.google.com/')

Create get-method for your class that calls driver.get. Then you can refer to it inside the class as self.get.
class CustomDriver:
def __init__(self, driver):
self.driver = driver
def get(self, url):
self.driver.get(url)
def another_method(self):
self.get("<some_url>")
# do some other stuff here...
# initiate driver first
driver = ...
drv = CustomDriver(driver)
drv.get("<some_url>")

self in Python class
self represents the instance of the class. By using the self keyword
we can access the attributes and methods of the class in python. It
binds the attributes with the given arguments.
In short, self is always pointing to current object.
But get() is method from the WebDriver implementation. So to access get() you have to invoke it through the instance of the WebDriver i.e. driver which you have already initialized through:
self.driver = webdriver.Chrome(options=self.options)

Related

How can I access base class elements using inheritance

I am using inheritance to access base class elements. I have defined driver object in environment class and inherited in base class. In base class I am trying to access this object.
However I am getting an error Environment has no object driver. How do I access this element?
class Environment(object):
def __init__(self):
driver = "webdriver.Chrome(D:\BrowserDriver\ChromeDriver\chromedriver.exe)"
print self.driver
class base(Environment):
def __init__(self):
drive = self.driver
def test_Home_Page(self):
# Screenshots relative paths
ss_path = "/Test_MercuryTours_HomePage/"
# Using the driver instances created in EnvironmentSetup
drive = self.driver
print drive
env=Environment()
print env.setUp()
b=base()
print b.drive
class Environment(object):
def __init__(self):
self.driver = "webdriver.Chrome(D:\BrowserDriver\ChromeDriver\chromedriver.exe)"
print self.driver
class base(Environment):
def __init__(self):
Environment.__init__(self)
self.drive = self.driver
b=base()
print b.drive
Add self to the variable driver, in the base class.
def __init__(self):
self.driver = "webdriver.C..."
ps: similarly, to access drive, you need to change it to self.drive .
In the base class, try this.
def __init__(self):
Environment.__init__(self)
self.driver = "webdriver.C..." .
Find out more about the Super keyword used for inheritance.

Appium with Python - setup class for webdriver

Programing is a new thing for me and probably I am missing something obvious.
I would like to create a separate file and class for setup my webdriver for Appium tests, but I got errors like:
in test_login main_page = MainPage(self.driver)
AttributeError: 'test_Login_iOS' object has no attribute 'driver'
Currently I have two files: one with test case and other with methods for test steps:
test_Login_iOS.py:
class test_Login_iOS(unittest.TestCase):
def setUp(self):
logging.info("WebDriver request initiated. Waiting for response, this may take a while.")
# choose desired capabilities from desired_capabilities.py
desired_capabilities = DesiredCapabilities.desired_capabilities_for_iOS_iPad
self.driver = webdriver.Remote("http://localhost:4723/wd/hub", desired_capabilities)
self.driver.implicitly_wait(15) # seconds
def test_login(self):
logging.info("starting Test Case 1: login into active account")
welcome_page = WelcomePage(self.driver)
welcome_page.click_login_button()
login_page = LoginPage(self.driver)
and second file, page_ios.py:
class BasePage(unittest.TestCase):
"""
:type driver: appium.webdriver.Remote
"""
def __init__(self, driver):
super().__init__()
self.driver = driver
When I add new test case I have to add to it the same setUp method like in previous test case, so I would like to create a new class "Setup" that could be shared across multiple test cases.
Goal is to move setUp method to separate file and new class.

Define custom function in selenium python

How I can define custom function and then use it in test function, it works when I run single test case but don't work when I run multiple test cases.
class AlphaTest(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Firefox()
self.driver.implicitly_wait(30)
self.driver.get("http://google.com/")
def asserTrueId(self, value):
self.assertTrue(self.driver.find_element_by_id(value))
time.sleep(1)
def test_flush_cache(self):
self.asserTrueId("block-menu-menu-menu-for-directories")
You could use unittest.setUpClass() to instantiate a class level driver instance. Similarly you can use tearDownClass() to clean up class level variables if required.
Since setUpClass() and tearDownClass() will only be run once inside your Test class you can use this to guarantee there is only one driver. Otherwise using setUp() would be run for each test method - each creating a browser instance each time - which could be slow and possibly memory inefficient.
class AlphaTest(unittest.TestCase):
#classmethod
def setUpClass(cls):
cls.driver = webdriver.Firefox()
cls.driver.implicitly_wait(30)
cls.driver.get("http://google.com/")
def asserTrueId(self, value):
self.assertTrue(self.driver.find_element_by_id(value))
time.sleep(1)
def test_flush_cache(self):
self.asserTrueId("block-menu-menu-menu-for-directories")

Pass self to decorator object

Having such decorator object
class wait_for_page_load(object):
def __init__(self, driver, time_to_wait=20):
self.driver = driver
self.time_to_wait = time_to_wait
def __call__(self, function):
#functools.wraps(function)
def wrapper(*args):
old_page = self.driver.find_element_by_tag_name('html')
function(*args)
WebDriverWait(self.driver, self.time_to_wait).until(staleness_of(old_page))
return wrapper
I want to apply it to method of another class, like this:
class VehiclePage(object):
def __init__(self, driver):
self.driver = driver
#wait_for_page_load(self.driver)
def open(self):
self.driver.get('%s/vehicles/' % BASE_URL)
This gives me an error. Is there a way to pass self.driver to decorator?
You don't have to pass self to a decorator object. If the decorator returns a function, then that function will get access to self when it is called. eg.
def pass_value(function):
def wrapper(self):
function(self, self.value)
return wrapper
class Printer(object):
def __init__(self, value):
self.value = value
#pass_value
def print_(self, v):
print v
Printer("blah").print_()
The one problem with this method is that it requires self to implement a specific interface (such as having a field called driver, rather than directly passing the driver to the decorator).
Your decorator would become:
def wait_for_page_load(time_to_wait=20):
def decorator(function):
#functools.wraps(function)
def wrapper(self, *args):
old_page = self.driver.find_element_by_tag_name('html')
function(self, *args)
WebDriverWait(self.driver, time_to_wait).until(staleness_of(old_page))
return wrapper
return decorator
Used as:
#wait_for_page_load() # brackets are needed
def open(self):
...
Short answer: No there is not.
Long answer:
The driver attribute is set when you instantiate the class. However, the decorator is run when the class is interpreted. That is, when the interpreter first reads it when loading the module. At this point, you don't have any instance ready. To do this kind of stuff you will have to refactor your code.
Also, even if that worked, you would end up using a single instance of your decorator class for all your objects. Probably not what you expected.
A simple workaround, though, could be to apply the decorator in __init__. Though not very elegant, that would work if you really need to apply the decorator.
def __init__(self, driver):
self.driver = driver
self.open = wait_for_page_load(self.driver)(self.open)
But then I believe you need to bind the wrapper to the class yourself by calling types.MethodType - honestly, it's probably better you just reorganize your code.

Python class mock. How can I get mock-class method calls information

I have a class named Client providing some service by its getResponse method. This class is used by other classes.
I make unit testing for class Driver who uses the Client class.
By using mock.patch, I replace the Client class by mock class called MockClient
which has the same getResponse method returning some predefined values.
It works great. But now I want to test parameters the getRsponse method was called with.
I want to do it by using the *assert_has_calls* method.
Did not find how to do it. Please advice.
Class under test:
# Driver and its Client
class Driver:
def __init__ (self):
self.client = Client()
def call(self, param):
return self.client.getResponse(param)
class Client:
def getResponse(self, param):
return 'original'
This is the Test class with the mock class:
import unittest
import mock
import driver
from driver import Driver
from driver import Client
class MockClient:
def getResponse(self,param):
return 'mock class'
class TestIt(unittest.TestCase):
def setUp(self):
self.mock_client = mock.patch('driver.Client',create=True, new=MockClient)
self.mock_client.start()
def tearDown(self):
self.mock_client.stop()
def test_call(self):
driver = Driver()
result = driver.call('test')
self.assertEqual(result, 'mock class')
assert_has_calls expects a list of call objects that it can compare to.
You can get a call object by calling the mock.call helper function with your expected arguments and keyword arguments.
This example is straight from the documentation and illustrates the usage quite well:
mock = Mock(return_value=None)
mock(1)
mock(2)
mock(3)
mock(4)
calls = [call(2), call(3)]
mock.assert_has_calls(calls)
calls = [call(4), call(2), call(3)]
mock.assert_has_calls(calls, any_order=True)

Categories