Unittest - testing properties (read-only attributes)

Discussion in 'Python' started by Paul Moore, Feb 21, 2005.

  1. Paul Moore

    Paul Moore Guest

    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.
    --
    XML with elementtree is what makes me never have think about XML
    again. -- Istvan Albert
    Paul Moore, Feb 21, 2005
    #1
    1. Advertising

  2. Paul Moore wrote:

    > 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")


    --
    Regards,

    Diez B. Roggisch
    Diez B. Roggisch, Feb 21, 2005
    #2
    1. Advertising

  3. Paul Moore

    Roy Smith Guest

    In article <>, Paul Moore <>
    wrote:

    > 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)
    Roy Smith, Feb 21, 2005
    #3
  4. Paul Moore

    Peter Hansen Guest

    Roy Smith wrote:
    > 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
    Peter Hansen, Feb 21, 2005
    #4
  5. Paul Moore

    Paul Rubin Guest

    Peter Hansen <> writes:
    > > 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...


    Yes, assignment expressions could make code more readable, if Python
    supported them.
    Paul Rubin, Feb 21, 2005
    #5
  6. Paul Moore

    Paul Moore Guest

    Peter Hansen <> writes:

    > Roy Smith wrote:
    >> 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...


    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.
    --
    It was a machine, and as such only understood one thing. Being clobbered
    with big hammers was something it could relate to. -- Tom Holt
    Paul Moore, Feb 21, 2005
    #6
  7. Paul Moore

    Duncan Booth Guest

    Paul Rubin wrote:

    > Peter Hansen <> writes:
    >> > 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...

    >
    > 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.
    Duncan Booth, Feb 21, 2005
    #7
  8. Paul Moore

    Duncan Booth Guest

    Duncan Booth wrote:

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


    Although of course it would help if still inside a lambda.
    Duncan Booth, Feb 21, 2005
    #8
  9. Paul Moore

    Paul Rubin Guest

    Duncan Booth <> writes:
    > 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 ;).
    Paul Rubin, Feb 21, 2005
    #9
  10. Paul Moore

    Roy Smith Guest

    Paul Rubin <http://> wrote:
    > 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. :)
    Roy Smith, Feb 21, 2005
    #10
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. keithb
    Replies:
    2
    Views:
    8,007
    keithb
    Jun 7, 2006
  2. Paul  Moore
    Replies:
    1
    Views:
    384
    Paul Moore
    Oct 14, 2008
  3. TechieInsights
    Replies:
    5
    Views:
    349
    josh logan
    Feb 12, 2009
  4. Thomas Guettler
    Replies:
    1
    Views:
    303
    Peter Otten
    Nov 25, 2009
  5. Tim Chase
    Replies:
    8
    Views:
    235
    Roy Smith
    Sep 29, 2011
Loading...

Share This Page