Testbed presentation mode test failure on 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
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