beeware / beeware/toga

Testbed presentation mode test failure on macOS

Open
#3,295 5 comments 0 reactions 0 assignees View on GitHub
bug macOS
Dominant language
Python
Stars
5.4k
Forks
827
Avg merge
15h 39m
Merged PRs (30d)
40

Description

### Describe the bug

I'm consistently getting the same reported failure for `tests/app/test_desktop.py::test_presentation_mode`, though it doesn't always *look* the same, visually. Sometimes the testbed app exits normally... but sometimes both my monitors turn all black and stay that way. Unplugging one and plugging it back in puts things back to normal, but nothing short of that seems to. I've confirmed none of these work:

- Command + tab
- Escape
- Command + Option + Escape to try and open Force Quit
- Fn + F or Cmd + Ctrl + F to try and exit full screen
- Frantic mouse-clicking

Other things are still running normally on my computer, despite the black screens — music and sounds still play, and if I run the whole testbed, the rest of the tests run and pass as usual; I just can't see the results until I unplug/plug a monitor.

### Steps to reproduce

`briefcase run --test -- tests/app/test_desktop.py::test_presentation_mode` (or `dev`)

### Expected behavior

I mean ideally the test would pass, but even if it fails, hopefully it shouldn't lock up both my monitors.

### Screenshots

_No response_

### Environment

- Operating System: macOS Sonoma 14.7.3
- Python version: 3.13.0
- Software versions:
- Briefcase: 0.3.22
- Toga: Main branch

### Logs

```
=================================== FAILURES ===================================
____________________________ test_presentation_mode ____________________________
Traceback (most recent call last):
File "/Users/charles/toga_dev/toga/testbed/build/testbed/macos/app/Toga Testbed.app/Contents/Resources/app_packages/_pytest/runner.py", line 341, in from_call
result: TResult | None = func()
~~~~^^
File "/Users/charles/toga_dev/toga/testbed/build/testbed/macos/app/Toga Testbed.app/Contents/Resources/app_packages/_pytest/runner.py", line 242, in
lambda: runtest_hook(item=item, **kwds), when=when, reraise=reraise
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^
File "/Users/charles/toga_dev/toga/testbed/build/testbed/macos/app/Toga Testbed.app/Contents/Resources/app_packages/pluggy/_hooks.py", line 513, in __call__
return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult)
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/charles/toga_dev/toga/testbed/build/testbed/macos/app/Toga Testbed.app/Contents/Resources/app_packages/pluggy/_manager.py", line 120, in _hookexec
return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/charles/toga_dev/toga/testbed/build/testbed/macos/app/Toga Testbed.app/Contents/Resources/app_packages/pluggy/_callers.py", line 139, in _multicall
raise exception.with_traceback(exception.__traceback__)
File "/Users/charles/toga_dev/toga/testbed/build/testbed/macos/app/Toga Testbed.app/Contents/Resources/app_packages/pluggy/_callers.py", line 122, in _multicall
teardown.throw(exception) # type: ignore[union-attr]
~~~~~~~~~~~~~~^^^^^^^^^^^
File "/Users/charles/toga_dev/toga/testbed/build/testbed/macos/app/Toga Testbed.app/Contents/Resources/app_packages/_pytest/threadexception.py", line 92, in pytest_runtest_call
yield from thread_exception_runtest_hook()
File "/Users/charles/toga_dev/toga/testbed/build/testbed/macos/app/Toga Testbed.app/Contents/Resources/app_packages/_pytest/threadexception.py", line 68, in thread_exception_runtest_hook
yield
File "/Users/charles/toga_dev/toga/testbed/build/testbed/macos/app/Toga Testbed.app/Contents/Resources/app_packages/pluggy/_callers.py", line 122, in _multicall
teardown.throw(exception) # type: ignore[union-attr]
~~~~~~~~~~~~~~^^^^^^^^^^^
File "/Users/charles/toga_dev/toga/testbed/build/testbed/macos/app/Toga Testbed.app/Contents/Resources/app_packages/_pytest/unraisableexception.py", line 95, in pytest_runtest_call
yield from unraisable_exception_runtest_hook()
File "/Users/charles/toga_dev/toga/testbed/build/testbed/macos/app/Toga Testbed.app/Contents/Resources/app_packages/_pytest/unraisableexception.py", line 70, in unraisable_exception_runtest_hook
yield
File "/Users/charles/toga_dev/toga/testbed/build/testbed/macos/app/Toga Testbed.app/Contents/Resources/app_packages/pluggy/_callers.py", line 122, in _multicall
teardown.throw(exception) # type: ignore[union-attr]
~~~~~~~~~~~~~~^^^^^^^^^^^
File "/Users/charles/toga_dev/toga/testbed/build/testbed/macos/app/Toga Testbed.app/Contents/Resources/app_packages/_pytest/logging.py", line 846, in pytest_runtest_call
yield from self._runtest_for(item, "call")
File "/Users/charles/toga_dev/toga/testbed/build/testbed/macos/app/Toga Testbed.app/Contents/Resources/app_packages/_pytest/logging.py", line 829, in _runtest_for
yield
File "/Users/charles/toga_dev/toga/testbed/build/testbed/macos/app/Toga Testbed.app/Contents/Resources/app_packages/pluggy/_callers.py", line 122, in _multicall
teardown.throw(exception) # type: ignore[union-attr]
~~~~~~~~~~~~~~^^^^^^^^^^^
File "/Users/charles/toga_dev/toga/testbed/build/testbed/macos/app/Toga Testbed.app/Contents/Resources/app_packages/_pytest/capture.py", line 898, in pytest_runtest_call
return (yield)
^^^^^
File "/Users/charles/toga_dev/toga/testbed/build/testbed/macos/app/Toga Testbed.app/Contents/Resources/app_packages/pluggy/_callers.py", line 122, in _multicall
teardown.throw(exception) # type: ignore[union-attr]
~~~~~~~~~~~~~~^^^^^^^^^^^
File "/Users/charles/toga_dev/toga/testbed/build/testbed/macos/app/Toga Testbed.app/Contents/Resources/app_packages/_pytest/skipping.py", line 257, in pytest_runtest_call
return (yield)
^^^^^
File "/Users/charles/toga_dev/toga/testbed/build/testbed/macos/app/Toga Testbed.app/Contents/Resources/app_packages/pluggy/_callers.py", line 103, in _multicall
res = hook_impl.function(*args)
File "/Users/charles/toga_dev/toga/testbed/build/testbed/macos/app/Toga Testbed.app/Contents/Resources/app_packages/_pytest/runner.py", line 174, in pytest_runtest_call
item.runtest()
~~~~~~~~~~~~^^
File "/Users/charles/toga_dev/toga/testbed/build/testbed/macos/app/Toga Testbed.app/Contents/Resources/app_packages/pytest_asyncio/plugin.py", line 533, in runtest
super().runtest()
~~~~~~~~~~~~~~~^^
File "/Users/charles/toga_dev/toga/testbed/build/testbed/macos/app/Toga Testbed.app/Contents/Resources/app_packages/_pytest/python.py", line 1627, in runtest
self.ihook.pytest_pyfunc_call(pyfuncitem=self)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
File "/Users/charles/toga_dev/toga/testbed/build/testbed/macos/app/Toga Testbed.app/Contents/Resources/app_packages/pluggy/_hooks.py", line 513, in __call__
return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult)
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/charles/toga_dev/toga/testbed/build/testbed/macos/app/Toga Testbed.app/Contents/Resources/app_packages/pluggy/_manager.py", line 120, in _hookexec
return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/charles/toga_dev/toga/testbed/build/testbed/macos/app/Toga Testbed.app/Contents/Resources/app_packages/pluggy/_callers.py", line 182, in _multicall
return outcome.get_result()
~~~~~~~~~~~~~~~~~~^^
File "/Users/charles/toga_dev/toga/testbed/build/testbed/macos/app/Toga Testbed.app/Contents/Resources/app_packages/pluggy/_result.py", line 100, in get_result
raise exc.with_traceback(exc.__traceback__)
File "/Users/charles/toga_dev/toga/testbed/build/testbed/macos/app/Toga Testbed.app/Contents/Resources/app_packages/pluggy/_callers.py", line 103, in _multicall
res = hook_impl.function(*args)
File "/Users/charles/toga_dev/toga/testbed/build/testbed/macos/app/Toga Testbed.app/Contents/Resources/app_packages/_pytest/python.py", line 159, in pytest_pyfunc_call
result = testfunction(**testargs)
File "/Users/charles/toga_dev/toga/testbed/build/testbed/macos/app/Toga Testbed.app/Contents/Resources/app_packages/pytest_asyncio/plugin.py", line 1052, in inner
_loop.run_until_complete(task)
~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/Users/charles/toga_dev/toga/testbed/build/testbed/macos/app/Toga Testbed.app/Contents/Resources/app/tests/conftest.py", line 167, in run_until_complete
return asyncio.run_coroutine_threadsafe(coro, self.loop).result()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^
File "/Users/charles/toga_dev/toga/testbed/build/testbed/macos/app/Toga Testbed.app/Contents/Frameworks/Python.framework/Versions/3.13/lib/python3.13/concurrent/futures/_base.py", line 456, in result
return self.__get_result()
~~~~~~~~~~~~~~~~~^^
File "/Users/charles/toga_dev/toga/testbed/build/testbed/macos/app/Toga Testbed.app/Contents/Frameworks/Python.framework/Versions/3.13/lib/python3.13/concurrent/futures/_base.py", line 401, in __get_result
raise self._exception
File "/Users/charles/toga_dev/toga/testbed/build/testbed/macos/app/Toga Testbed.app/Contents/Resources/app/tests/app/test_desktop.py", line 287, in test_presentation_mode
assert (
...<2 lines>...
), f"{window_information['window'].title}:"
AssertionError: Test Window 0:
assert ==
+ where = .instantaneous_state
+ and = WindowState.PRESENTATION
---------------------------- Captured stdout setup -----------------------------
Resetting main_window
----------------------------- Captured stdout call -----------------------------
All Test Windows are visible
App is in presentation mode
App is in presentation mode
=========================== short test summary info ============================
FAILED tests/app/test_desktop.py::test_presentation_mode - AssertionError: Test Window 0:
assert ==
+ where = .instantaneous_state
+ and = WindowState.PRESENTATION
============================== 1 failed in 6.54s ===============================
```

### Additional context

_No response_

Contributor guide

Open the contributing guide

Research direction

Start with tests/app/test_desktop.py::test_presentation_mode and reproduce it using `briefcase run --test -- tests/app/test_desktop.py::test_presentation_mode` on macOS. Compare the expected PRESENTATION state with the observed NORMAL state and investigate the reported black-screen behavior. Done means the test no longer fails or locks both monitors during presentation-mode testing.

Written by the indexing model from the issue text.

Assessment

Tech stack
macos, python
Domain
desktop, testing-qa
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.