Calling a method of one class in another class - python

I'm attempting to call test_check_footer_visible in another .py file.
origin.py has:
class FooterSection(unittest.TestCase):
"""
"""
browser = None
site_url = None
def setUp(self):
self.browser.open(self.site_url)
self.browser.window_maximize()
# make footer section
self._footer = FooterPage(self.browser)
def test_check_footer_visible(self):
#press the page down
self.browser.key_down_native("34")
self.browser.key_down_native("34")
self.browser.key_down_native("34")
print "Page down"
time.sleep (10)
Now in dest.py I need to call test_check_footer_visible(). How do I do that?
dest.py has the following format:
class TestPageErrorSection(unittest.TestCase):
"""
"""
browser = None
site_url = None
def setUp(self):
global SITE_URL, BROWSER
if not BROWSER:
BROWSER = self.browser
if not SITE_URL:
SITE_URL = self.site_url
BROWSER.open(SITE_URL)
BROWSER.window_maximize()
print 'page not found 404 error'
self._pageerror_section = ErrorSection(BROWSER)
def _primary_navigation(self):
# I want to call test_check_footer_visible here.
I tried everything in Call Class Method From Another Class

You can't (without doing some really shady things -- see comments by #glglgl) -- at least not without changing your code somewhat. The reason you can't is because test_check_footer_visible will assert that the first element passed in is an instance of the class FooterSection (which it isn't -- it's an instance of TestPageErrorSection). You have (at least) a couple of options for the re-factor.
1) Make TestPageErrorSection inherit from FooterSection and use that function directly (e.g. self.test_check_footer_visible() This doesn't seem like a very good option to me based on the class names
2) Make test_check_footer_visible() a regular function. It can then be called from either class.
3) Create a 3rd class (e.g. SectionBase), put test_check_footer_visible on that class and have your other 2 classes inherit from it.

Related

Python and nesting classes for structure

I am having a bit of trouble with nesting classes in python.
Mind you my code below is a simplified example showing what I want to do, but basically I want to use nested classes to make my code more structured and make sure I don't run into name clashes for certain functions.
See here my example code:
class Chrome:
def __init__(self, url='http://localhost:4723/wd/hub'):
# Capabilities
capabilities = Capabilities.chrome()
# Start session
self.driver = webdriver.Remote(url, capabilities)
def get_url(self, url):
# Go to URL
self.driver.get(url)
class actions:
#staticmethod
def browse_url(url):
# Go to url
Chrome.get_url(url)
if __name__ == '__main__':
browser = Chrome()
browser.actions.browse_url('https://www.google.com')
The goal as you can see in if __name__ == '__main__' is to be able to start a browser instance, and then call functions in a structured way.
However I have no clue on how to correctly achieve the browser.actions.browse_url('https://www.google.com') concept.
How is this done correctly ?
You should call get_url from an instance of Chrome and not the class itself, since it's an instance method and not a static one:
...
#staticmethod
def browse_url(url):
Chrome().get_url(url)
...
if __name__ == '__main__':
Chrome.actions.browse_url('https://www.google.com')

I'm getting an invallid syntax error with my class

I've been learning python for a while now but I really want to start using oop but I'm having trouble understanding it, please can you tell me where I'm going wrong with my class.
class Savecookies():
driver = webdriver.Firefox()
def __init__(self, site, url):
self.site = site
self.url = url
def twitter(driver, self.site, self.url):
if __name__=='__main__':
cooks = Savecookies('twitter', 'https://twitter.com/')
My error:
File "twitter_test2.py", line 26
def twitter(driver, self.site, self.url):
^
SyntaxError: invalid syntax
def twitter(driver, self.site, self.url):
What’s that?
First of all, methods need a body. Otherwise they are incomplete. The simplest body would be to just do pass (i.e. do nothing). But you probably want to add actual stuff in there.
Second, your arguments make no sense at all. The first argument of a method is self, and then you specify which other arguments you want the method to accept. And argument names need to be valid variables, so you cannot have a dot in there. And if you want the method to access self.site and self.url, you can just do that without needing to pass it to the function (since you have access to self). In your case, you already have the site and url from the Savecookies object, so you probably want something like this:
def twitter(self, driver):
# Do something useful here
print(self.site, self.url)
print(driver)
in case twitter is an instance method
change
def twitter(driver, self.site, self.url):
to
def twitter(self):
#now do something with the params
print(self.driver, self.site, self.url)
Basically, let it access the site and url instance attributes set by __init__
and let it access the driver class attribute set in the class
Both types of attributes can be reached through self., there is no need to pass it again as a parameter.

How to present a class as a function?

As it was unclear earlier I am posting this scenario:
class Scraper:
def __init__(self,url):
self.start_page = url
def parse_html(self):
pass
def get_all_links(self):
pass
def run(self):
#parse html, get all links, parse them and when done...
return links
Now in a task queue like rq
from rq import Queue
from worker import conn
q = Queue(connection=conn)
result = q.enqueue(what_function, 'http://stackoverflow.com')
I want to know what this what_function would be? I remembered Django does something similar with their CBVs so I used that analogy but it wasn't so clear.
I have a class like
class A:
def run(self,arg):
#do something
I need to past this to a task queue, so I can do something like
a = A()
b = a.run
# q is the queue object
q.enqueue(b,some_arg)
I'd want to know what other method is there to do this, for example, Django does it in their Class Based Views,
class YourListView(ListView):
#code for your view
which is eventually passed as a function
your_view = YourListView.as_view()
How is it done?
Edit: to elaborate, django's class based views are converted to functions because the argument in the pattern function expects a function. Similarly, you might have a function which accepts the following argument
task_queue(callback_function, *parameters):
#add to queue and return result when done
but the functionality of callback_function might have been mostly implemented in a class, which has a run() method via which the process is ran.
I think you're describing a classmethod:
class MyClass(object):
#classmethod
def as_view(cls):
'''method intended to be called on the class, not an instance'''
return cls(instantiation, args)
which could be used like this:
call_later = MyClass.as_view
and later called:
call_later()
Most frequently, class methods are used to instantiate a new instance, for example, dict's fromkeys classmethod:
dict.fromkeys(['foo', 'bar'])
returns a new dict instance:
{'foo': None, 'bar': None}
Update
In your example,
result = q.enqueue(what_function, 'http://stackoverflow.com')
you want to know what_function could go there. I saw a very similar example from the RQ home page. That's got to be your own implementation. It's going to be something you can call with your code. It's only going to be called with that argument once, so if using a class, your __init__ should look more like this, if you want to use Scraper for your what_function replacement:
class Scraper:
def __init__(self,url):
self.start_page = url
self.run()
# etc...
If you want to use a class method, that might look like this:
class Scraper:
def __init__(self,url):
self.start_page = url
def parse_html(self):
pass
def get_all_links(self):
pass
#classmethod
def run(cls, url):
instance = cls(url)
#parse html, get all links, parse them and when done...
return links
And then your what_function would be Scraper.run.

Web.py pass parameter to GET/POST function via ajax call on form submit

I have a main page that has a GET and a POST function. The POST function gets data from a search screen and should pass this information, via an ajax call, to the worldMarkers class. This is separate because it will be needed for other aspects of the application.
The goal of this, is to have a user press submit on index and during the POST call, it is able to limit the results retrieved. This logic exists in the worldMarkers class.
class index(object):
def GET(self):
# do things to generate the page
return html
def POST(self):
continents = web.input(search_continents=[])
countries = web.input(search_countries=[])
searchDict = {}
if continents['search_continents']:
searchDict['continents'] = continents['search_continents']
if countries['search_countries']:
searchDict['countries'] = countries['search_countries']
markers = worldMarkers()
# Yes, this just spits out the results, nothing fancy right now
return markers.GET()
#alternatively,
#return markers.GET(searchDict)
class worldMarkers(object):
def __init__(self, **kargs):
self.searchDict = None
if 'searchDict' in kargs:
self.searchDict = kargs['searchDict']
def GET(self):
print "SearchDict: %s" % (self.searchDict)
# No searchDict data exists
The first option, with no parameters to markers.GET() means that none of my search criteria has been passed. If I do markers.GET(searchDict), I receive this error:
<type 'exceptions.TypeError'> at /
GET() takes exactly 1 argument (2 given)
How can I pass my search parameters to the worldMarkers class?
It looks like you should actually create an instance of worldMarkers as follows in order for your searchDict to exist:
markers = worldMarkers(searchDict=searchDict)
Right now, you're creating it without the argument:
markers = worldMarkers()
and in that case, the condition if 'searchDict' in kargs is false and self.searchDict = kargs['searchDict'] is not run.
And, as #TyrantWave points out, your GET is not really prepared to take any arguments since it is only declared as def GET(self). See the last sample code of this section of the docs.

Sending object C from class A to class B

I can't figure out how to design classes in my system.
In classA I create object selenium (it simulates user actions at website).
In this ClassA I create another objects like SearchScreen, Payment_Screen and Summary_Screen.
# -*- coding: utf-8 -*-
from selenium import selenium
import unittest, time, re
class OurSiteTestCases(unittest.TestCase):
def setUp(self):
self.verificationErrors = []
self.selenium = selenium("localhost", 5555, "*chrome", "http://www.someaddress.com/")
time.sleep(5)
self.selenium.start()
def test_buy_coffee(self):
sel = self.selenium
sel.open('/')
sel.window_maximize()
search_screen=SearchScreen(self.selenium)
search_screen.choose('lavazza')
payment_screen=PaymentScreen(self.selenium)
payment_screen.fill_test_data()
summary_screen=SummaryScreen(selenium)
summary_screen.accept()
def tearDown(self):
self.selenium.stop()
self.assertEqual([], self.verificationErrors)
if __name__ == "__main__":
unittest.main()
It's example SearchScreen module:
class SearchScreen:
def __init__(self,selenium):
self.selenium=selenium
def search(self):
self.selenium.click('css=button.search')
I want to know if there is anything ok with a design of those classes?
Your approach is fine. You have a set of tool classes, each of which needs to know its target. Then you have a toolkit class that coordinates these tools on a particular target.
class AgreePrice:
def __init__(self, connection): ...
class PlaceOrder:
def __init__(self, connection): ...
class ConfirmAvailability:
def __init__(self, connection): ...
class BookingService:
def __init__(self, connection): ...
def book(self):
for Command in (ConfirmAvailability, AgreePrice, PlaceOrder):
command = Command(self.connection)
command.run()
assert command.success()
There's nothing at all wrong with those kinds of class structures, in fact they come up all the time, and are a reasonably good design when the individual 'tool' classes can't be placed conveniently in one function.
If ever you find yourself with a class that has tens of methods in it, of which many can be grouped according to specific tasks, this is a good refactor.
As a general rule you want to make sure that your 'tool' classes (SearchScreen, etc) are at a conceptually lower level than your controller (your test cases). Which they are for you.
At their simplest these tool classes are a form of the Function Object design pattern. Although in your case, you are calling more than just one method on each object, so they are a little more sophisticated.
Or, in short. Your design is fine, and very common.
If SearchScreen/PaymentScreen/SummaryScreen only performs test logic, it looks to me like you might as well just put that logic in utility methods of OurSiteTestCases.
Possible design for the test_buy_coffee method (depending on what you actually do in SearchScreen et al):
def test_buy_coffee(self):
sel = self.selenium
sel.open('/')
sel.window_maximize()
# Replace SearchScreen
self.__choose_search()
# Replace PaymentScreen
self.__fill_payment_data()
# Replace SummaryScreen
self.__accept_summary()
Edit:
If you need to factor out the test logic in __choose_search, __fill_payment_data and __accept_summary, to share it between tests, you may write corresponding utility test functions in a common module/package. Or, you could write a test baseclass which contains the selenium object (self.selenium) and has the "protected" utility methods _choose_search, _fill_payment_data and _accept_summary. It all depends on what's practical in your case :)
Maybe you can use Chain of Responsibility pattern:
Definition:
Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.
The example is in c# the:
Handler h1 = new ConcreteHandler1();
Handler h2 = new ConcreteHandler2();
Handler h3 = new ConcreteHandler3();
h1.SetSuccessor(h2);
h2.SetSuccessor(h3);
// Generate and process request
int[] requests = { 2, 5, 14, 22, 18, 3, 27, 20 };
foreach (int request in requests)
{
h1.HandleRequest(request);
}
Here is you can see the complete documentation: http://www.dofactory.com/Patterns/PatternChain.aspx#_self1

Categories