enthought / enthought/traitsui

Test interaction arising from use of UITester

Open
#2,071 3 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
306
Forks
99
PR merge metrics
No merged PRs in 30d

Description

This is a boiled-down version of a test interaction seen on a real project using TraitsUI and the UITester.

The test class has three tests: `test1`, `test2` and `test3`, with `test3` identical to `test1`. When run on my machine, the tests run in the order `test1`, `test2`, `test3`. But `test1` passes, while `test3` logs an exception (though it also passes), so either there's some source of non-determinism in `test1` / `test3`, or something about `test2` is altering global state.

Most of the ingredients here seem to be essential to reproducing the interaction, including the `UITester`, the `FileEditor`, the `GuiTestAssistant` and the `ProgressEditor`.

Here's the script:

```python
import unittest
from pathlib import Path

from pyface.ui.qt.util.gui_test_assistant import GuiTestAssistant
from traits.api import Directory, Enum, HasStrictTraits, Instance, Int, observe
from traits.observation.events import TraitChangeEvent
from traitsui.api import ProgressEditor, UItem, View
from traitsui.testing.api import UITester

class ProgressBar(HasStrictTraits):
value = Int()
traits_view = View(UItem("value", editor=ProgressEditor()))

class Model1(HasStrictTraits):
directory = Directory()
model_directory = Instance(Path)
state = Enum(["Idle", "Refreshing"])

@observe("model_directory")
def _refresh(self, event: TraitChangeEvent) -> None:
if self.state != "Idle":
raise RuntimeError("Cannot refresh when not in idle state.")
self.state = "Refreshing"

@observe("directory")
def _update_model_directory(self, event: TraitChangeEvent) -> None:
self.model_directory = Path(self.directory)

traits_view = View(UItem("directory", enabled_when=f"state == 'Idle'"))

class Model2(HasStrictTraits):
progress_bar = Instance(ProgressBar, ())
traits_view = View(UItem("progress_bar", style="custom"))

class TestModels(GuiTestAssistant, unittest.TestCase):
def test1(self) -> None:
view = Model1()
with UITester(auto_process_events=False).create_ui(view):
view.directory = Path.cwd()

def test2(self) -> None:
view = Model2()
with UITester(auto_process_events=False).create_ui(view):
pass

def test3(self) -> None:
view = Model1()
with UITester(auto_process_events=False).create_ui(view):
view.directory = Path.cwd()
```

Here's the output on my machine (macOS/M3, EDM environment, Python 3.11.14, TraitsUI 8.0.0-3, traits 7.1.0-1, pyside6 6.10.0-2)

```
~/Desktop % edm run -e testenv -- python -m unittest -v weird_test.py
test1 (weird_test.TestModels.test1) ... ok
test2 (weird_test.TestModels.test2) ... ok
test3 (weird_test.TestModels.test3) ... Exception occurred in traits notification handler for event object: TraitChangeEvent(object=, name='model_directory', old=PosixPath('/Users/mdickinson/Desktop'), new=PosixPath('.'))
Traceback (most recent call last):
File "/Users/mdickinson/.edm/envs/testenv/lib/python3.11/site-packages/traits/observation/_trait_event_notifier.py", line 122, in __call__
self.dispatcher(handler, event)
File "/Users/mdickinson/.edm/envs/testenv/lib/python3.11/site-packages/traits/observation/observe.py", line 43, in dispatch_same
handler(event)
File "/Users/mdickinson/Desktop/weird_test.py", line 24, in _refresh
raise RuntimeError("Cannot refresh when not in idle state.")
RuntimeError: Cannot refresh when not in idle state.
ok

----------------------------------------------------------------------
Ran 3 tests in 0.377s

OK
```

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.