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
Related
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 trying to write a way of testing some XML files. The XML files describe input into a scientific analysis program where various parameters can be defined. I want to write unittests for my XML files so I know that the program is configured correctly.
I'm currently doing this as a library with a base test class containing various tests and some mixins for subcomponents. But the subcomponents are repeated a number of times so I want the tests to run once for each mixin e.g.:
class BaseTest(object):
xmlfile = '...'
...
class ComponentMixin(object):
xmlid = None #
var = None #
def test_var(self):
assert self.var == "whatever_the_value_is_in self.xmlfile"
# ... and a number of other tests and variables.
... now for each analysis there can be a number of components defined with different parameters. I'm hoping to do something like this --
class MyFirstComponentMixin(ComponentMixin):
xmlid = 'component1'
var = 'one'
class MySecondComponentMixin(ComponentMixin):
xmlid = 'component2'
var = 'two'
class MyTest(BaseTest, MyFirstComponentMixin, MySecondComponentMixin, unittest.TestCase):
xmlfile = '...'
... but the problem is that test_var will only be called for component2 and not component2. Is there a way around this, or a better solution?
As you were advised in comment: composition is better solution for your problem than inheritance. The idea is to define multiple standalone TestCases (parts) for pieces of the XML file and then compose them into single TestSuite (composite).
Library
It is a base class for part.
class BaseTestCase(unittest.TestCase):
xmlfile = None # will be set by containing test suite
It is an abstract component test case implementation.
class ComponentTestCase(BaseTestCase):
xmlid = None
var = None
def test_var(self):
assert self.var == "whatever_the_value_is_in self.xmlfile"
It is a base for our composite. It defines convenient copying of the xmlfile from composite to its parts.
class BaseTestSuite(unittest.TestSuite):
xmlfile = None
def addTest(self, test):
if isinstance(test, BaseTestCase):
test.xmlfile = self.xmlfile
super(BaseTestSuite, self).addTest(test)
Usage
It is specific part, which tests some specific aspect of the XML:
class MySpecificTestCase(BaseTestCase):
def test_something_specific(self):
self.assertEqual(4, 2 + 2)
These are parts, which test particular components:
class MyFirstComponentTestCase(ComponentTestCase):
xmlid = 'component1'
var = 'one'
class MySecondComponentTestCase(ComponentTestCase):
xmlid = 'component2'
var = 'two'
Here is a composite with XML you want to test.
class MyTest(BaseTestSuite):
xmlfile = '<some_xml></some_xml>'
We define load_tests to return TestSuite with all TestCases included.
def load_tests(loader, standard_tests, pattern):
return MyTest((
loader.loadTestsFromTestCase(MySpecificTestCase),
loader.loadTestsFromTestCase(MyFirstComponentTestCase),
loader.loadTestsFromTestCase(MySecondComponentTestCase)
))
This approach has one limitation: you can't test few XML files from the single Python file. Basically you can, but output won't help you to identify, which XML file is broken.
Your case is a bit tricky. unittest were designed to test code, not data. Maybe validation against XML schema is what you need.
While the title of this question was exactly what I was looking for, the answer doesn't exactly fit my case.
Perhaps because this question is about testing of data, rather than code.
Still, I found this example (code copy-pasted below) of using multiple inheritances to implement multiple mixins.
Before following this pattern, though, I recommend reading up on multiple inheritance in python is hard - by Ned Batchelder, and this Deep Dive into Python Mixins and Multiple Inheritance.
import unittest
from unittest import TestCase
"""
Showcase how to use mixins and multiple inheritance to write tests
"""
class BaseTest(TestCase):
"""
A base class to be inheritated by actuall test classes.
"""
def setUp(self): # 3
print("BaseTest:setUp called")
self.boo = "gladen sum"
#classmethod
def setUpClass(cls): # 1
print("BaseTest::setUpClass called")
cls.browser = 'musaka'
class FullDBMixin(object):
def setUp(self): # 5
super(FullDBMixin, self).setUp()
print("FullDBMixin::setUp called with instance attribute [boo] = %s" % self.boo)
class LoginMixin(object):
#classmethod
def setUpClass(cls): # 2
super(LoginMixin, cls).setUpClass()
print("LoginMixin::setUpClass called")
def setUp(self): # 4
super(LoginMixin, self).setUp()
print("LoginMixin::setUp called")
self.login()
def login(self):
print("LoginMixin::login called with class attribute [browser] %s" % self.browser)
# order of inheritance **matters**
class TestAuthontecation(LoginMixin, FullDBMixin , BaseTest):
def test_user_dashboard(self):
# test stuff without needing to setup the db or login the user
pass
if __name__ == '__main__':
unittest.main()
# georgi#georgi-laptop:~$ python test.py
# BaseTest::setUpClass called
# LoginMixin::setUpClass called
# BaseTest:setUp called
# FullDBMixin::setUp called with instance attribute [boo] = gladen sum
# LoginMixin::setUp called
# LoginMixin::login called with class attribute [browser] musaka
# .
# ----------------------------------------------------------------------
# Ran 1 test in 0.000s
# OK
I have a File Field in my Plone product that I want to allow the user to "Turn Off" blob storage. The file will be stored elsewhere. I can't seem to do it.
Below is my attempt. I can't get Products.Archetypes.Field.ObjectField.setStorage() to recognize that this 'noStorage' instance "provides" IStorage.
Much inconsequential code has been removed for brevity, but the complete source can be found at https://github.com/flipmcf/rfa.kaltura
The Archetype schema includes "ATBlob.schema" to pull in the "File" field, then:
class KalturaVideo(ATBlob, KalturaBase.KalturaContentMixin):
nostorage = NoStorage()
directlyProvides(nostorage, INoStorage)
def __init__(self, oid, **kwargs):
if settings.storageMethod == u"No Local Storage":
import pdb; pdb.set_trace() #
#(Pdb) IStorage.providedBy(self.nostorage)
#True
self.getField('file').setStorage(self, self.nostorage)
My Storage class and interface is really boring:
from zope.interface import implements
from ZODB.interfaces import IStorage
from zope.component.zcml import interface
from zope.interface import Interface
class INoStorage(IStorage):
pass
class NoStorage(object):
"""Completely skip storage on Plone."""
implements(INoStorage)
def __init__(self):
pass
def close():
pass
def getName():
return "NoStorage - Blackhole"
#etc... lots of implemented methods that do nothing.
configure.zcml in the 'storage' package also:
<adapter
factory=".storage.NoStorage"
provides=".storage.INoStorage"
for="Products.Archetypes.interfaces.field.IObjectField"
/>
<adapter
factory=".storage.NoStorage"
provides=".storage.IStorage"
for="Products.Archetypes.interfaces.field.IObjectField"
/>
Now, within the setStorage() method of Products.Archetypes.Field.ObjectField:
def setStorage(self, instance, storage):
import pdb; pdb.set_trace()
#(Pdb) IStorage.providedBy(storage)
#False
#HeadDesk
if not IStorage.providedBy(storage):
raise ObjectFieldException, "Not a valid Storage method"
And when I debug, IStorage.providedBy(storage) returns False
Why would it return False in setStorage and True in the calling code? Am I not registering the interface correctly?
Note that in the module Products.Archetypes.Field, the IStorage instance there is actually sourced from this:
from Products.Archetypes.interfaces.storage import IStorage
Comparing the interface resolution order (via __iro__) we get
>>> from pprint import pprint as pp
>>> pp(ZODB.interfaces.IStorage.__iro__)
(<InterfaceClass ZODB.interfaces.IStorage>,
<InterfaceClass zope.interface.Interface>)
>>> pp(Products.Archetypes.interfaces.storage.IStorage.__iro__)
(<InterfaceClass Products.Archetypes.interfaces.storage.IStorage>,
<InterfaceClass zope.interface.Interface>)
As the INoStorage was subclassed from ZODB.interfaces.IStorage, and that interface class isn't the parent of Products.Archetypes.interfaces.storage.IStorage which the setStorage calls providedBy on, the NoStorage class as define will not satisfy that check. To solve this, just have INoStorage simply inherit from the Archetype version of the IStorage and implement all its methods and it should work as intend.
That said, you could simply your code somewhat further with regards to the way you provide the interfaces, see this example:
>>> class INoStorage(Products.Archetypes.interfaces.storage.IStorage):
... pass
...
>>> class NoStorage(object):
... zope.interface.implements(INoStorage)
...
>>> nostorage = NoStorage()
>>> Products.Archetypes.interfaces.storage.IStorage.providedBy(nostorage)
True
Inheritances of the Interface subclasses will persist correctly through without extra directlyProvides definitions, so you can just drop that extra call inside the KalturaVideo class definition. Naturally, you can just do from ... import IStorage and simply that to class INoStorage(IStorage). The example was done so to make things more explicitly visible.
Context
I'm trying to implement some variant of strategy pattern in Python 2.7.
I want to be able to instantiate a 'my_strategy' base class, but switch between different implementations of a 'score' method at run-time.
I will have many common methods in 'my_strategy' but a bunch of 'score' implementations.
The main illustrates how I want to use it.
Here the scoring implementation is dummy of course.
What I tried (i.e. My code so far)
strategy.py:
from algo_one import *
#from algo_two import *
class my_strategy ( object ):
def __init__(self, candidate = ""):
self.candidate = candidate
self.method = 'default'
self.no = 10
self._algo = algo_one
def set_strategy(self, strategy='default'):
self.strategy = strategy
if self.strategy == 'algo_one':
self._algo = algo_one
elif self.strategy == 'algo_two':
# self._algo = algo_two
pass
else:
self._algo = None
def score(self, *args):
if len(args) > 0:
self.candidate = args[0]
self._algo.score(self.candidate)
if __name__ == "__main__":
s = my_strategy()
s.strategy = 'algo_one'
s.candidate = "hello world"
print s.score()
print s.score("hi")
# s.set_method('algo_two')
# print s.score("hi")
I want to save the selected strategy in some sort of private pointer to the sub-class method.
algo_one.py:
from strategy import my_strategy
class algo_one ( my_strategy ):
def score(self, candidate):
return len(candidate)*self.no
I could have a class-less method, but later I'll need to access public variables of the base class.
algo_two.py:
from strategy import my_strategy
class algo_two ( my_strategy ):
def score(self, candidate):
return len(candidate)*3
I have an empty init.py too.
The errors
1.
in score self._algo.score(self.candidate)
TypeError: unbound method score() must be called with algo_one
instance as first argument (got str instance instead)
2.
If I uncomment the import of the second strategy:
from algo_two import *
I get the following error.
ImportError: cannot import name my_strategy
My guess is that I run into some sort of circular dependency.
3.
from algo_one import *
This is obviously not pretty (unable to detect undefined names), but if I
from algo_one import algo_one
I get
ImportError: cannot import name algo_one
Question
I think the errors are intertwined and that my approach, as a whole, may be flawed. If not just addressing the error, I'm looking for suggestions to improve the design. Or any comment, really. Also I'm open to suggestions regarding the title of this question. Thank you!
You make it much more complicated than it needs to be. Python functions are first class objects so the simplest way to implement the strategy pattern in Python is to pass a 'strategy' function to your "context" object (the one that uses the strategy). The fine part is that any callable object (ie: any object implementing the __call__ method) will work.
def default_score_strategy(scorer):
return len(scorer.candidate) * 3
def universal_answer_score_strategy(scorer):
return 42 # definitly the universal answer <g>
class ComplicatedStrategy(object):
def __init__(self, factor):
self.factor = factor
def __call__(self, scorer):
return len(scorer.candidate) * self.factor
class Scorer(object):
def __init__(self, candidate="", strategy=default_score_strategy):
self.candidate = candidate
self.strategy = strategy
def score(self):
return self.strategy(self)
s1 = Scorer("foo")
s2 = Scorer("bar", strategy=universal_answer_score_strategy)
s3 = Scorer("baaz", strategy=ComplicatedStrategy(365))
Note that your strategies dont have to be in the same module as the Scorer class (well, except the default one of course), and that the module containing the Scorer class doesn't have to import the stratgeies modules - nor know anything about where the strategies are defined:
# main.py
from mylib.scores import Scorer
from myapp.strategies import my_custom_strategy
s = Scorer("yadda", my_custom_strategy)
You don't instantiate your algo object in the __init__ method. Remember, to instantiate a class object, you need to call it:
self._algo = algo_one()
Yes, that's a circular dependency. I don't see however why algo_one and algo_two need to inherit from my_strategy at all. Just make them plain objects, or inherit a base class stored somewhere else. Or, keep them all in the same file - there's no reason to necessarily have classes in separate files in Python.
This is the same problem as 2.
One of your main problems are that your algorithms try to subclass from your base class, which is a huge design flaw (you already noticed that). Use a simple method binding instead, which deals with all the necessary things:
def algo_one(candidate):
# do stuff
return "A fluffy unicorn"
def algo_two(candidate):
# do some other stuff
return "Awesome rabbits"
# not really necessary, just to make it easier to add new algorithms
STRATEGIES = { "one": algo_one, "two": algo_two }
class Strategy(object):
def __init__(self):
...
def set_strategy(self, which):
if which not in STRATEGIES:
raise ValueError("'%s' is an unknown strategy" % which)
# compatibility checks about the entries in STRATEGIES omitted here
self._algo = STRATEGIES[which]
def score(self, *args):
# ...
return self._algo(...)
If you need a more complex approach (this however depends on your requirements), in which everyone knows about each other, split the algorithms and strategy chooser into different classes referencing each other (shortened version below):
class ScoreAlgo(object):
def __init__(self, parent):
self._strategy = parent # if you need a back-reference, just be aware of circular dependencies in the garbage collection
def __del__(self):
self._strategy = None # resolve circular dependency for the GC
def score(self, candidate):
return None
class Strategy(object):
def __init__(self):
...
def set_strategy(self, ...):
...
self._algo = ScoreAlgo(self)
def score(self, ...):
return self._algo.score(...)
(If you need a huge variety of algorithms, you should make ScoreAlgo an abstract base class, for which subclasses have to implement the score() method).
You also could use a mixin pattern (which is a bit more formal than the method binding) or several other ways. This however depends on your overall requirements.
EDIT: I just added a returnto both def score(): stubs to avoid confusion about why those might not return anything.
I'm working on a project in Tornado that relies heavily on the asynchronous features of the library. By following the chat demo, I've managed to get long-polling working with my application, however I seem to have run into a problem with the way it all works.
Basically what I want to do is be able to call a function on the UpdateManager class and have it finish the asynchronous request for any callbacks in the waiting list. Here's some code to explain what I mean:
update.py:
class UpdateManager(object):
waiters = []
attrs = []
other_attrs = []
def set_attr(self, attr):
self.attrs.append(attr)
def set_other_attr(self, attr):
self.other_attrs.append(attr)
def add_callback(self, cb):
self.waiters.append(cb)
def send(self):
for cb in self.waiters:
cb(self.attrs, self.other_attrs)
class LongPoll(tornado.web.RequestHandler, UpdateManager):
#tornado.web.asynchronous
def get(self):
self.add_callback(self.finish_request)
def finish_request(self, attrs, other_attrs):
# Render some JSON to give the client, etc...
class SetSomething(tornado.web.RequestHandler):
def post(self):
# Handle the stuff...
self.add_attr(some_attr)
(There's more code implementing the URL handlers/server and such, however I don't believe that's necessary for this question)
So what I want to do is make it so I can call UpdateManager.send from another place in my application and still have it send the data to the waiting clients. The problem is that when you try to do this:
from update import UpdateManager
UpdateManager.send()
it only gets the UpdateManager class, not the instance of it that is holding user callbacks. So my question is: is there any way to create a persistent object with Tornado that will allow me to share a single instance of UpdateManager throughout my application?
Don't use instance methods - use class methods (after all, you're already using class attributes, you just might not realize it). That way, you don't have to instantiate the object, and can instead just call the methods of the class itself, which acts as a singleton:
class UpdateManager(object):
waiters = []
attrs = []
other_attrs = []
#classmethod
def set_attr(cls, attr):
cls.attrs.append(attr)
#classmethod
def set_other_attr(cls, attr):
cls.other_attrs.append(attr)
#classmethod
def add_callback(cls, cb):
cls.waiters.append(cb)
#classmethod
def send(cls):
for cb in cls.waiters:
cb(cls.attrs, cls.other_attrs)
This will make...
from update import UpdateManager
UpdateManager.send()
work as you desire it to.