Not able call a local method from setUpClass - python

My code:
class TestSystemPromotion(unittest2.TestCase):
#classmethod
def setUpClass(self):
...
self.setup_test_data()
..
def test_something(self):
...
def setup_test_data(self):
...
if __name__ == '__main__':
unittest2.main()
Error which I'm getting is:
TypeError: unbound method setup_test_data() must be called with TestSystemPromotion
instance as first argument (got nothing instead)

You can't call instance methods from class methods. Either consider using setUp instead, or make setup_test_data a class method too. Also, it's better if you called the argument cls instead of self to avoid the confusion - the first argument to the class method is the class, not the instance. The instance (self) doesn't exist at all when setUpClass is called.
class TestSystemPromotion(unittest2.TestCase):
#classmethod
def setUpClass(cls):
cls.setup_test_data()
#classmethod
def setup_test_data(cls):
...
def test_something(self):
...
Or:
class TestSystemPromotion(unittest2.TestCase):
def setUp(self):
self.setup_test_data()
def setup_test_data(self):
...
def test_something(self):
...
For better comprehension, you can think of it this way: cls == type(self)

Related

unittest.TestCase setUpClass override and inheritance

As can be seen in the following example, I've defined a BaseClass for all tests, each test case class inherits the base class.
Both classes needs to perform a one time initialization, when test_vehicles.py is executed, I need to make sure that setUpClass of the base class is invoked as well, not sure how to achieve that where #classmethod is in play.
# base.py
import unittest
class BaseClass(unittest.TestCase):
#classmethod
def setUpClass(cls):
# initialize stuff
cls.app = app
# test_vehicles.py
class VehiclesTestCase(BaseClass):
#classmethod
def setUpClass(cls):
# initialize stuff
cls.vehicle_id = '123'
def test_get_vehicle(self):
resp = self.app.get(self.vehicle_id)
self.assertEqual(resp, True)
if __name__ == '__main__':
unittest.main()
Similar question Using super with a class method. More information yoou can get also from https://docs.python.org/3/library/functions.html#super.
Solution: use super function and bound to the class
# test_vehicles.py
class VehiclesTestCase(BaseClass):
#classmethod
def setUpClass(cls):
super(VehiclesTestCase, cls).setUpClass()
cls.vehicle_id = '123'
if __name__ == '__main__':
unittest.main()
You can use the super method in the inherited classes' setUpClass to access the setUpClass of BaseClass:
super().setUpClass()
If you don't want to call super in each child class, just create an abstract method in BaseClass and call it in setUpClass of BaseClass. VehiclesTestCase now has to implement this abstract method:
class BaseClass(unittest.TestCase):
#classmethod
def setUpClass(cls):
# initialize stuff
cls.app = app
#classmethod
def _setUpChild(cls):
raise NotImplementedError
class VehiclesTestCase(BaseClass):
#classmethod
def _setUpChild(cls):
# initialize stuff
cls.vehicle_id = '123'
def test_get_vehicle(self):
resp = self.app.get(self.vehicle_id)
self.assertEqual(resp, True)
I would also recommend that BaseClass is not a TestCase if it cannot run by itself. It would always show up in your test report although it has no tests. You can instead use multi-inheritance:
class BaseClass:
# Stuff
class VehiclesTestCase(BaseClass, unittest.TestCase):
# Stuff
The order of inheritance is important. Method lookup is done from left to right. This means that BaseClass.setUpClass overrides the setUpClass of TestCase.

How to call a function within a class with self

Suppose I have the following:
class myClass:
def foo(self):
# do something
How can I call myClass from inside the class without declaring an new myClass Object? i.e. I'd like something like
class myClass:
def foo(self):
# do something
if __name__ == '__main__':
# call foo
or without main:
class myClass:
def foo(self):
# do something
# call foo
Right now I keep getting either the error that self is not defined, or the error that foo expects 1 argument but 0 was provided.
You cannot. The function is part of the class, so to access it you must access the class first.
class myClass:
def foo(self):
# do something
myClass().foo()
If you just don't want to type myClass().foo() but only foo then you could just return the myClass() in a new function called foo():
def foo():
return myClass().foo()
You can use self in a class when calling from inside the class itself:
class myClass:
def __init__(self):
pass
def foo(self):
pass
def method2(self):
self.foo()
This does not create a new instance of myClass like calling myClass().foo() would, and you do not need to pass the same arguments that you may have passed in myClass.
Since foo() has a self parameter, that means it is an instance method, and therefore it is only callable from an instance of myClass.
If you want foo to be callable without an instance, use the #staticmethod decorator, and remove self from the parameter list.

Python class decorator, cannot use constructor

So I have the following decorator code
class Factory:
def __init__(self, cls):
self.cls = cls
def __instancecheck__(self, inst):
return isinstance(inst, self.cls)
def Produce(self):
return self.cls()
And the following class code
#Factory
class Foo:
def __init__(self, arg):
self.arg = arg
def method(self): pass
Which works great. Allows me to do stuff like
Foo.Produce().method()
Instead of
instance = Foo()
instance.method()
But now I cant use the class constructor normally
Foo(arg)
Gives the exception 'Factory object is not callable'. My question is the following: How can I make a decorator that allows me to instantiate the decorated class using its constructor, but also allows me to use a function in the decorator?
Alternative ways I'd rather not use:
Skip the constructor. Always use <Class>.Produce() (and use *args/**kwargs to make it abstract/reusable.
Use setters in all the classes, and make them return self so they can be chained.
Make a class containing the produce method and extend this class.
The exception is telling you all you need to know, just add a __call__ method:
class Factory:
# ...
def __call__(self, *args, **kwargs):
return self.cls(*args, **kwargs)
If all you want to do is to add a Produce function to the class, you can rewrite your decorator like this:
def Factory(cls):
def Produce():
return cls()
cls.Produce= Produce # add the function to the class
return cls

Refer to a class outside its method?

I need to deliver something like this in my program
class the_class_name(Parent):
the_attribute = self.parent_class_method()
#the parent class method will return a value
#but I cannot use self here since there's no self
How can I carry this out? Is there any other alternative that can do the job for me?
I have tried using __init__ like this:
def __init__(self):
Parent.__init__(self)
self.attribute = self.the_method()
But then I have problem creating the object, it won't receive any parameters that the Parent class normally receives anymore
Sounds like you are looking for __init__:
class TheClassName(Parent):
def __init__(self):
# Set attribute to the result of the parent method
self.attribute = super(TheClassName, self).the_method()
EDIT
If your parent class has parameters in it's own __init__ function, include them in the child class:
class Parent(object):
def __init__(self, foo, bar):
...
#classmethod
def the_method(cls):
...
class TheClassName(Parent):
def __init__(self, foo, bar):
super(TheClassName, self).__init__(foo, bar)
self.attribute = super(TheClassName, self).the_method()
I don't quite understand why you don't just call the parent method on your child object when you need the value though.
There is no self at that point of the creation of the subclass, nor is there an instance of the Parent class. That means the only Parent class methods you could call would have to be either static or class methods.
To demonstrate:
class Parent(object):
#staticmethod
def static_method():
return 42
#classmethod
def class_method(cls):
return 43
class TheClassName(Parent):
the_attribute = Parent.static_method()
another_attribute = Parent.class_method()
print(TheClassName.the_attribute) # -> 42
print(TheClassName.another_attribute) # -> 43
You must use class methods, declared with the #classmethod decorator, or a #staticmethod. The #classmethod decorator is preferable so that inheritance is handled correctly, i.e. the method is invoked on the derived class (a bit of a technicality, if you are still learning this).
class Alpha(object):
#classmethod
def method1(cls):
return 'method1 has been called on {}'.format(cls)
class Beta(Alpha):
def __init__(self):
self.myattr = Beta.method1()
print(Beta().myattr)
method1 has been called on class <'__main__.Beta'>
Use
super(ClassName, self).methodname(arg)
inside a method
def child_method(self, arg):
super(ClassName, self).methodname(arg)
You cannot use self outside a method.

When running a method from a Python superclass, how can I know the name of the child class that invoked it?

Let's say I have this parent class:
class BaseTestCase(unittest.TestCase):
#classmethod
def setUpClass(cls):
# I want to assign the name of the class that called
# the super class in a variable.
cls.child_class_name = ??
# Do some more stuff...
And I have this class that inherits from the BaseTestCase class above:
class MyTestCase(BaseTestCase):
#classmethod
def setUpClass(cls):
# Call SetUpClass from parent (BaseTestCase)
super(cls, cls).setUpClass()
# Do more stuff...
Since many classes can inherit from the same parent class. How can I know the name of the class that invoked the parent class in a given time?
I hope my question make sense. :S
cls.__name__ is always the name of the current class, because cls is bound the actual class object on which the class method was called.
In other words, cls is not a reference to the class on which the method is defined.
Note that you should not use super(cls, cls)! That'll lead to infinite recursion if you were to create a derived class from MyTestCase! Use the actual class, always:
class MyTestCase(BaseTestCase):
#classmethod
def setUpClass(cls):
# Call SetUpClass from parent (BaseTestCase)
super(MyTestCase, cls).setUpClass()
# Do more stuff...
Demo:
>>> class Foo(object):
... #classmethod
... def spam(cls):
... print(cls.__name__)
...
>>> class Bar(Foo):
... #classmethod
... def spam(cls):
... super(Bar, cls).spam()
...
>>> Bar.spam()
Bar
>>> Foo.spam()
Foo

Categories