I tried to use setUpClass() method for the first time in my life and wrote:
class TestDownload(unittest.TestCase):
def setUpClass(cls):
config.fs = True
and got:
Ran 0 tests in 0.004s
FAILED (errors=1)
Failure
Traceback (most recent call last):
File "/opt/anaconda3/lib/python3.5/unittest/suite.py", line 163, in _handleClassSetUp
setUpClass()
TypeError: setUpClass() missing 1 required positional argument: 'cls'
What does it mean and how to satisfy it?
You need to put a #classmethod decorator before def setUpClass(cls).
class TestDownload(unittest.TestCase):
#classmethod
def setUpClass(cls):
config.fs = True
The setupClass docs are here and classmethod docs here.
What happens is that in suite.py line 163 the setUpClass gets called on the class (not an instance) as a simple function (as opposed to a bound method). There is no argument passed silently to setUpClass, hence the error message.
By adding the #classmethod decorator, you are saying that when TestDownload.setupClass() is called, the first argument is the class TestDownload itself.
Adding #classmethod before setUp and tearDown will resolve the issue. #classmethod is bound to the class.
class LoginTest(unittest.TestCase):
#classmethod
def setUpClass(cls):
**Your code**
#classmethod
def tearDownClass(self):
Related
I am trying to do the following in python3:
class Parent:
#classmethod
def show(cls, message):
print(f'{message}')
#classmethod
def ask(cls, message):
cls.show(f'{message}???')
class Child(Parent):
#property
def name(self):
return 'John'
def show(self, message):
print(f'{self.name}: {message}')
instance = Child()
instance.ask('what')
But it then complains
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 7, in ask
TypeError: Child.show() missing 1 required positional argument: 'message'
even so child.show works as expected. So it seems that child.ask is calling Parent.show... I tried to mark Child.show as classmethod too, but then the cls.name is not showing the expected output:
class Child2(Parent):
#property
def name(self):
return 'John'
#classmethod
def show(cls, message):
print(f'{cls.name}: {message}')
instance2 = Child2()
instance2.ask('what')
this shows
<property object at 0xfc7b90>: what???
Is there a way to override a parent classmethod with a non-classmethod, but keeping other parent classmethod to call the overridden one?
I found it hard to follow for the second half of the question but there was an issue I saw and it might help you solve your problem.
When you said even so child.show works as expected. So it seems that child.ask is calling Parent.show, thats not what is happening.
When you called instance.ask("what"), it called the #classmethod decorated method of the Child class (which is inherited from the parent). This ask method is passing the class Child as the first argument, (not the instance you created). This means the line
cls.show(f'{message}???')
is equivalent to
Child.show(f'{message}???') # because cls is the Class not the instance
The show method inside the Child class is an instance method and expects the first argument to be the actual instance (self) but the string f'{message}???' is being passed to it and it expects a second message string to be passed so that's why its is throwing an error.
Hope this helped
I've 2 files: customer.py & agent.py. It looks like this:
customer.py:
from agent import KeyAgent
class CustomerController(object):
def __init__(self, container):
self.key = container.agent
def delete(self, path):
KeyAgent.delele_customer_node()
agent.py:
class KeyAgent(service.Service):
def __init__(self):
pass
def delele_customer_node():
....
Python is throwing this exception while running:
exceptions.AttributeError: class KeyAgent has no attribute 'delele_customer_node()'
Even though I've imported KeyAgent class from agent.py why method delele_customer_node() is not accessible from delete() of customer.py?
You must have misspelled the method name (delele? or delete?). The KeyAgent class does have a method delete_customer_node (I will assume that was a typo).
>>> class KeyAgent(object):
... def delete_customer():
... pass
...
>>> KeyAgent.delete_customer
<unbound method KeyAgent.delete_customer>
That means, the method is there. However your code is quite broken. Unless you use the staticmethod or classmethod decorators, the first argument of a method "must be" self, and you need to instantiate the class to call it. See what happens if you try to call this method directly:
>>> KeyAgent.delete_customer()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound method delete_customer() must be called with KeyAgent instance as first argument (got nothing instead)
I'm not sure why this is happening. It seems to think that "self" requires an argument, which doesn't make any sense.
Here's my code:
class Animal:
def __init__(self):
self.quality = 1
class Bear(Animal):
def __init__(self):
Animal.__init__(self)
def getImage(self):
return "bear.ppm"
class Fish(Animal):
def __init__(self):
Animal.__init__(self)
def getImage(self):
return "fish.ppm"
And the error I get is:
Traceback (most recent call last):
File "<pyshell#1>", line 1, in <module>
Bear.getImage()
TypeError: getImage() takes exactly 1 argument (0 given)
You have to instantiate Bear before you call getImage():
b = Bear()
b.getImage()
getImage is an instance method, so it is only designed to be called on a specific instance of the Bear class. The state of that instance is what is passed as the self variable to getImage. Calling b.getImage() is equivalent to this:
b = Bear()
Bear.getImage(b)
So, without an instance of Bear, there is nothing that can be used for the self argument, which is why you see that exception when you called Bear.getImage(). See the documentation on Python instance methods for more information.
If you want to be able to call getImage on the class Bear rather than on a specific instance, you need to make it a static method, using the #staticmethod decorator:
class Bear(Animal):
def __init__(self):
Animal.__init__(self)
#staticmethod
def getImage():
return "bear.ppm"
Then you could call Bear.getImage().
getImage() is an instance method, so it can only be called with a instantiation of Bear class. So here is how you can do it:
Bear().getImage()
or
be = Bear()
be.getImage()
I'm quite a beginner in Python and started designing a unit test in Python and i need to post some messages to the server before i run the test class (cause it's gonna search for them). Thus i need to call a non-static method postMessages().
the stack-trace of the error i'm getting is this-
Error
Traceback (most recent call last):
File ".../TestMsgs.py", line 23, in setUpClass
instance = cls()
File ".../python2.7/unittest/case.py", line 191, in __init__
(self.__class__, methodName))
ValueError: no such test method in <class 'TestMsgs.TestMsgs'>: runTest
i have something like this in the code:
class A(object):
def postMessages(self):
print "i post messages in the server!"
class B(A):
#classmethod
def setUpClass(cls):
cls.foo() # should post messages for the tests in the class to work on
There's no option, right now, to make foo static. How can i instantiate B (or A, for that matter) in postMessages() so i can use it in setUpClass() ?
After having a read through the __init__ method for TestCase I see that you need to provide a test method name to it. The default is "runTest" which is why that error was popping up.
import unittest
class A(unittest.TestCase):
def postMessages(self):
print "i post messages in the server!"
class B(A):
#classmethod
def setUpClass(cls):
cls.foo(cls(methodName='test_method')) # should post messages for the tests in the class to work on
def foo(self):
self.postMessages()
def test_method(self):
pass
B.setUpClass()
You can see it running in an interactive Python console here. It will print out "i post messages in the server!"
The reason you need to pass in a valid method name in the class can be clearly seen in the source code for unittest:
class TestCase:
"""A class whose instances are single test cases."""
def __init__(self, methodName='runTest'):
"""Create an instance of the class that will use the named test
method when executed. Raises a ValueError if the instance does
not have a method with the specified name.
"""
try:
self._testMethodName = methodName
testMethod = getattr(self, methodName)
self._testMethodDoc = testMethod.__doc__
except AttributeError:
raise ValueError, "no such test method in %s: %s" % \
(self.__class__, methodName)
If you want to pass in parameters to the method that you have just passed in then you would need to do something like
class A(unittest.TestCase):
def foo(self, arg1):
pass
a = A(methodName='foo')
a.foo('an_argument')
But this whole question just feels really wrong. You should refactor rather than have a static method calling an instance method. It's just silly.
Trying to mock out calls to pyazure library for django testing, but I can't figure out how to mock out the PyAzure class constructor so that it doesn't cause a TypeError. Is there a better way to approach mocking out an access library that generates a connection object?
Anything I've tried other than None generates a TypeError, which means I can't really even begin to test any of the PyAzure connection methods with actual return values. What is the best way to replace a working class with a fake class using mock?
Test Error:
======================================================================
ERROR: test_management_certificate_connect (azure_cloud.tests.ViewsTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/bschott/Source/django-nimbis/apps/azure_cloud/tests.py", line 107, in test_management_certificate_connect
self.cert1.connect()
File "/Users/bschott/Source/django-nimbis/apps/azure_cloud/models.py", line 242, in connect
subscription_id=self.subscription.subscription_id)
TypeError: __init__() should return None, not 'FakeAzure'
----------------------------------------------------------------------
tests.py:
class ViewsTest(TestCase):
def setUp(self):
...
self.cert1 = ManagementCertificate.objects.create(
name="cert1",
subscription=self.subscription1,
management_cert=File(open(__file__), "cert1.pem"),
owner=self.user1)
...
class FakeAzure(object):
""" testing class for azure """
def list_services(self):
return ['service1', 'service2', 'service3']
def list_storages(self):
return ['storage1', 'storage2', 'storage3']
#mock.patch.object(pyazure.PyAzure, '__init__')
def test_management_certificate_connect(self, mock_pyazure_init):
mock_pyazure_init.return_value = self.FakeAzure()
self.cert1.connect()
assert mock_pyazure_init.called
models.py
class ManagementCertificate(models.Model):
# support connection caching to azure
_cached_connection = None
def connect(self):
"""
Connect to the management interface using these credentials.
"""
if not self._cached_connection:
self._cached_connection = pyazure.PyAzure(
management_cert_path=self.management_cert.path,
subscription_id=self.subscription.subscription_id)
logging.debug(self._cached_connection)
return self._cached_connection
You seem to have a misconception about what __init__() does. Its purpose is to initialise an instance that was already created earlier. The first argument to __init__() is self, which is the instance, so you can see it was already allocated when __init__() is called.
There is a method __new__() that is called before __init__() to create the actual instance. I think it would be much easier, though, to replace the whole class by a mock class, instead of mocking single methods.