enthought / enthought/traits

Explain why exceptions don't bubble up in observers

Open
#1,726 0 comments 1 reaction 0 assignees View on GitHub
component: documentation
Dominant language
Python
Stars
462
Forks
90
PR merge metrics
No merged PRs in 30d

Description

In the sample below exceptions that are raised through `observe` cannot be caught in unit tests. It's expected behavior, but it may be surprising to some.

```
import unittest

from traits.api import HasTraits, Int, observe

class Person(HasTraits):
age = Int()

@observe("age")
def update_age(self, event):
if self.age > 15:
print("Raising an exception")
raise ValueError("I do not want to get old")

class TestPerson(unittest.TestCase):
def test_update_age(self):
# given
steve = Person(age=10)

# when / then
with self.assertRaises(ValueError) as err:
steve.age = 18

self.assertIn("I do not want to get old", str(err.exception))
```

The following explanation from @mdickinson could be cleaned up and integrated in the docs:

There are mechanisms that allow exceptions in observe handlers to be propagated; that's sometimes useful during testing.
But raising an exception in an observer, while it might be tempting, isn't really a terribly useful thing to do - there's no sensible place for that exception to be propagated to.
IOW, an exception raised in an observer is almost always a coding bug.
In particular, you should never try to use observers for validation of an assignment to a trait - that doesn't work, because the assignment has already happened.

For testing and debugging, see https://docs.enthought.com/traits/traits_user_manual/debugging.html#re-raising-exceptions-in-change-handlers, and in particular push_exception_handler.
Note that there are two versions of `push_exception_handler`: one for `on_trait_change` and one for `observe`, so you need to use both if you want to catch all exceptions.
But beware doing this in tests by default, since now your test logic isn't necessarily exercising the same code paths that your business logic is.
It's quite possible to end up with broken business logic that passes test cases as a result.

Internal discussion thread: https://enthought.slack.com/archives/C024RRPHD/p1667297991245249

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.