Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Explain why exceptions don't bubble up in observers #1726

Open
achabotl opened this issue Nov 1, 2022 · 0 comments
Open

Explain why exceptions don't bubble up in observers #1726

achabotl opened this issue Nov 1, 2022 · 0 comments
Labels
component: documentation Issues related to the Sphinx documentation

Comments

@achabotl
Copy link
Member

achabotl commented Nov 1, 2022

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

@achabotl achabotl added the component: documentation Issues related to the Sphinx documentation label Nov 1, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: documentation Issues related to the Sphinx documentation
Projects
None yet
Development

No branches or pull requests

1 participant