Unittest - testing properties (read-only attributes)

P

Paul Moore

I have a class with a read-only attribute, and I want to add a unit
test to ensure that it really *is* read-only. I can do this as

def test_readonly(self):
"""Value and multiplier must be readonly"""
try:
self.combat.value = 1
self.fail("Value is not read only")
except AttributeError:
pass

That works, but it seems a bit clumsy. Is there a better way?

Thanks,
Paul.
 
D

Diez B. Roggisch

Paul said:
I have a class with a read-only attribute, and I want to add a unit
test to ensure that it really *is* read-only. I can do this as

def test_readonly(self):
"""Value and multiplier must be readonly"""
try:
self.combat.value = 1
self.fail("Value is not read only")
except AttributeError:
pass

That works, but it seems a bit clumsy. Is there a better way?


By using setattr, you could refactor the above code into a function. Looks
like this (untested):

def test_readonly(self, instance, attribute, value=1):
"""Value and multiplier must be readonly"""
try:
setattr(instance, attribute, value)
self.fail("Value is not read only")
except AttributeError:
pass


Then the testing becomes one line:

self.test_readonly(self.combat, "value")
 
R

Roy Smith

Paul Moore <[email protected]> said:
I have a class with a read-only attribute, and I want to add a unit
test to ensure that it really *is* read-only. I can do this as

def test_readonly(self):
"""Value and multiplier must be readonly"""
try:
self.combat.value = 1
self.fail("Value is not read only")
except AttributeError:
pass

That works, but it seems a bit clumsy. Is there a better way?

Thanks,
Paul.

You want something like

self.assertRaises(AttributeError, lambda: self.combat.value = 1)
 
P

Peter Hansen

Roy said:
You want something like

self.assertRaises(AttributeError, lambda: self.combat.value = 1)

Or, combining the two responses and avoiding the lambda:

self.assertRaises(AttributeError, setattr, self.combat, 'value', 1)

Hmm... this might be a case where the lambda form is actually the
more readable one...

-Peter
 
P

Paul Rubin

Peter Hansen said:
Or, combining the two responses and avoiding the lambda:

self.assertRaises(AttributeError, setattr, self.combat, 'value', 1)

Hmm... this might be a case where the lambda form is actually the
more readable one...

Yes, assignment expressions could make code more readable, if Python
supported them.
 
P

Paul Moore

Peter Hansen said:
Or, combining the two responses and avoiding the lambda:

self.assertRaises(AttributeError, setattr, self.combat, 'value', 1)

Hmm... this might be a case where the lambda form is actually the
more readable one...

Thanks, I hadn't thought of setattr. I was bitten by the "assignment
is a statement, so can't be used in a lambda" issue, as well :)

Paul.
 
D

Duncan Booth

Paul said:
Yes, assignment expressions could make code more readable, if Python
supported them.

An assignment expression, if such a thing existed wouldn't help here.

The point being that the expression must be evaluated inside the exception
handler in assertRaises, so you either need to delay the evaluation with a
lambda, or by passing the function and arguments in separately. If you had
an assignment expression it would be roughly equivalent to:

self.assertRaises(AttributeError, setattr(self.combat, 'value', 1))

which will throw the AttributeError instead of passing the test.
 
P

Paul Rubin

Duncan Booth said:
An assignment expression, if such a thing existed wouldn't help here.

The point being that the expression must be evaluated inside the exception
handler in assertRaises, so you either need to delay the evaluation with a
lambda, or by passing the function and arguments in separately. If you had
an assignment expression it would be roughly equivalent to:

self.assertRaises(AttributeError, setattr(self.combat, 'value', 1))

which will throw the AttributeError instead of passing the test.

Yes. The example I quoted used an assignment expression inside a
lambda. The person who posted it, and the person who followed it up
with the setattr alternative, both didn't notice that the assignment
expression wasn't valid Python. However, my post came out sounding
grumpier than I intended ;).
 
R

Roy Smith

Paul Rubin said:
The example I quoted used an assignment expression inside a
lambda. The person who posted it,

That was me.
and the person who followed it up
with the setattr alternative, both didn't notice that the assignment
expression wasn't valid Python.

Ugh. No, I hadn't noticed it. Thanks for pointing it out.

I don't use lambdas much. In fact, the only time I ever do use them is for
an assertRaises unit test. I've always thought that "assignment is a
statement not an expression" was one of Python's warts, and this is just
another example of why it is. Of course, "lambda isn't just a def body" is
a wart too :)
However, my post came out sounding
grumpier than I intended ;).

Actually, I hadn't noticed that either. :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top