This is in Python 2.7. I have a class called class A, and there are some attributes that I want to throw an exception when being set by the user:
myA = A()
myA.myattribute = 9 # this should throw an error
I want to write a unittest that ensures that this throws an error.
After creating a test class and inheriting unittest.TestCase, I tried to write a test like this:
myA = A()
self.assertRaises(AttributeError, eval('myA.myattribute = 9'))
But, this throws a syntax error. However, if I try eval('myA.myattribute = 9'), it throws the attribute error, as it should.
How do I write a unittest to test this correctly?
Thanks.
You can also use assertRaises as a context manager:
with self.assertRaises(AttributeError):
myA.myattribute = 9
The documentation shows more examples for this if you are interested. The documentation for assertRaises has a lot more detail on this subject as well.
From that documentation:
If only the exception and possibly the msg arguments are given, return a context manager so that the code under test can be written
inline rather than as a function:
with self.assertRaises(SomeException):
do_something()
which is exactly what you are trying to do.
self.assertRaises takes a callable (and optionally one or more arguments for that callable) as its argument; you are providing the value that results from calling the callable with its arguments. The correct test would be self.assertRaises(AttributeError, eval, 'myA.myattribute = 9')
# Thanks to #mgilson for something that actually works while
# resembling the original attempt.
self.assertRaises(AttributeError, eval, 'myA.myattribute = 9', locals())
However, you should use assertRaises as a context manager, which allows you to write the much more natural
with self.assertRaises(AttributeError):
myA.myattribute = 9
Related
I am quite new to decorators, and I am using it in mocking a function; can someone kindly explain the following:
class TestTSE(...):
...
#patch.object(TSESubparser, 'parse_er_data', return_value=None)
def test_receive_timestamp(self, mock_parse_er_data_to_nothing):
packet = MagicMock(capture_timestamp=123456)
self.on_packet(packet)
assert self.context.capture_tstamp == 123456
I don't quite understand why we are passing a second argument mock_parse_er_data_to_nothing. I tried running the test without it and it fails.
I understand that we can call this function anything that we want? - why is this. And it is advisable that it starts with mock
I have a function of the form:
def my_function(arg):
f = get_anonymous_function(arg)
return f()
I want to test this function in mockito with py.test.
So I write my test as follows:
def test_my_function(when):
arg = mock()
f = mock()
when(my_module).get_anonymous_function(arg).thenReturn(f)
expected = mock()
when(f).thenReturn(expected)
actual = my_module.my_function(arg)
assert expected == actual
When I run such a test, actual is None. If I change when to when2, Mockito complains TypeError: can't guess origin of 'f'.
My provisional solution is to use f = lambda: return expected, and then skip the second when. This works, but feels not quite right. Is there a better way?
PS: "Don't use Mockito" is not really the answer I'm looking for. Likewise, "write my_function better" is not an option, as this sort of situation arises routinely when using external packages.
Figured it out. From the documentation (with typo corrected):
Mocks are by default callable. Configure the callable behavior using
when:
dummy = mock()
when(dummy).__call__(1).thenReturn(2)
I am using the skip decorator for a test:
#skip('I want this to skip')
def test_abc(self):
I also have a nose plugin to report test results with a defined
def beforeTest(self, *args, **kwargs):
the test case test_abc is getting captured by the beforeTest method. How can I check for the decorator value in my beforeTest method?
I see that the definition of unittest decorator has the following code:
test_item.__unittest_skip__ = True
test_item.__unittest_skip_why__ = reason
But I dont know how to access it from beforeTest.
When running args[0].test has the test case object but I can seem to find where __unittest_skip__ is defined
Thanks!
Looking at the source code, there doesn't seem to be a clean way to do this. TestCase seems to know what method it is testing based on the _testMethodName implementation detail. If you have a reference to the running test case (maybe args[0].test? I'm not familiar with nose...) you could use that, or you could parse it out of the return value from TestCase.id(). Assuming you aren't doing something really funky, it would be something like:
test_name = test_case.id().rsplit('.', 1)[-1]
test_method = getattr(test_case, test_name)
if getattr(test_method, '__unittest_skip__', False):
# Method skipped. Don't do normal stuff.
I have an outer function that calls an inner function by passing the arguments along. Is it possible to test that both functions throw the same exception/error without knowing the exact error type?
I'm looking for something like:
def test_invalidInput_throwsSameError(self):
arg = 'invalidarg'
self.assertRaisesSameError(
innerFunction(arg),
outerFunction(arg)
)
Assuming you're using unittest (and python2.7 or newer) and that you're not doing something pathological like raising old-style class instances as errors, you can get the exception from the error context if you use assertRaises as a context manager.
with self.assertRaises(Exception) as err_context1:
innerFunction(arg)
with self.assertRaises(Exception) as err_context2:
outerFunction(arg)
# Or some other measure of "sameness"
self.assertEqual(
type(err_context1.exception),
type(err_context2.exception))
First call the first function and capture what exception it raises:
try:
innerfunction(arg)
except Exception as e:
pass
else:
e = None
Then assert that the other function raises the same exception:
self.assertRaises(e, outerfunction, arg)
I believe this will do what you want; just add it as another method of your TestCase class:
def assertRaisesSameError(self, *funcs, bases=(Exception,)):
exceptions = []
for func in funcs:
with self.assertRaises(base) as error_context:
func()
exceptions.append(error_context.exception)
for exc in exceptions:
self.assertEqual(type(exc), type(exc[-1]))
I haven't tested this, but it should work. For simplicity this only takes functions with no arguments, so if your function does have arguments, you'll have to make a wrapper (even just with a lambda). It would not be hard at all to expand this to allow for passing in the *args and **kwargs.
Let me know of any changes anyone thinks should be made.
Is a way to see if a class responds to a method in Python? like in ruby:
class Fun
def hello
puts 'Hello'
end
end
fun = Fun.new
puts fun.respond_to? 'hello' # true
Also is there a way to see how many arguments the method requires?
Hmmm .... I'd think that hasattr and callable would be the easiest way to accomplish the same goal:
class Fun:
def hello(self):
print 'Hello'
hasattr(Fun, 'hello') # -> True
callable(Fun.hello) # -> True
You could, of course, call callable(Fun.hello) from within an exception handling suite:
try:
callable(Fun.goodbye)
except AttributeError, e:
return False
As for introspection on the number of required arguments; I think that would be of dubious value to the language (even if it existed in Python) because that would tell you nothing about the required semantics. Given both the ease with which one can define optional/defaulted arguments and variable argument functions and methods in Python it seems that knowing the "required" number of arguments for a function would be of very little value (from a programmatic/introspective perspective).
Has method:
func = getattr(Fun, "hello", None)
if callable(func):
...
Arity:
import inspect
args, varargs, varkw, defaults = inspect.getargspec(Fun.hello)
arity = len(args)
Note that arity can be pretty much anything if you have varargs and/or varkw not None.
dir(instance) returns a list of an objects attributes.
getattr(instance,"attr") returns an object's attribute.
callable(x) returns True if x is callable.
class Fun(object):
def hello(self):
print "Hello"
f = Fun()
callable(getattr(f,'hello'))
I am no Ruby expert, so I am not sure if this answers your question. I think you want to check if an object contains a method. There are numerous ways to do so. You can try to use the hasattr() function, to see if an object hast the method:
hasattr(fun, "hello") #True
Or you can follow the python guideline don't ask to ask, just ask so, just catch the exception thrown when the object doesn't have the method:
try:
fun.hello2()
except AttributeError:
print("fun does not have the attribute hello2")