Skip to content

Add custom approx() to help with floating point <= / >= testing#4504

Merged
HalfWhitt merged 5 commits into
beeware:mainfrom
HalfWhitt:widen-iOS-assertion
Jun 26, 2026
Merged

Add custom approx() to help with floating point <= / >= testing#4504
HalfWhitt merged 5 commits into
beeware:mainfrom
HalfWhitt:widen-iOS-assertion

Conversation

@HalfWhitt

@HalfWhitt HalfWhitt commented Jun 25, 2026

Copy link
Copy Markdown
Member

For reference, this is my current setup:

  • Python 3.12.13
  • Briefcase 0.4.2
  • Toga current main branch
  • iOS 18.1 simulator
  • macOS 14.8.7

I found that every single test in the iOS testbed was erroring out for me in setup:

__________________ ERROR at setup of test_unsupported_widget ___________________
Traceback (most recent call last):
[...]
  File "/Users/charles/Library/Developer/CoreSimulator/Devices/EF6E765C-63E6-483E-B45D-2217D4206454/data/Containers/Bundle/Application/2DF77722-55A1-4B8C-8034-5D92F1F3EBA5/Toga Testbed.app/app/tests_backend/window.py", line 43, in _assert_container_layout
    assert self.impl.container.content.native.frame.origin.y >= self.top_bar_height
AssertionError: assert 100.33333333333331 >= 100.33333333333334
 +  where 100.33333333333331 = <NSPoint(0.0, 100.33333333333331)>.y
 +    where <NSPoint(0.0, 100.33333333333331)> = <NSRect(NSPoint(0.0, 100.33333333333331), NSSize(402.0, 773.0))>.origin
 +      where <NSRect(NSPoint(0.0, 100.33333333333331), NSSize(402.0, 773.0))> = <ObjCInstance: TogaView at 0x13c2ba8a0: <TogaView: 0x13ca0e5c0; frame = (0 100.333; 402 773); backgroundColor = UIExtendedSRGBColorSpace 0.854902 0.647059 0.12549 1; layer = <CALayer: 0x600000267700>>>.frame
 +        where <ObjCInstance: TogaView at 0x13c2ba8a0: <TogaView: 0x13ca0e5c0; frame = (0 100.333; 402 773); backgroundColor = UIExtendedSRGBColorSpace 0.854902 0.647059 0.12549 1; layer = <CALayer: 0x600000267700>>> = <toga_iOS.widgets.box.Box object at 0x13b6f4f20>.native
 +          where <toga_iOS.widgets.box.Box object at 0x13b6f4f20> = <toga_iOS.container.NavigationContainer object at 0x13a44a0c0>.content
 +            where <toga_iOS.container.NavigationContainer object at 0x13a44a0c0> = <toga_iOS.window.MainWindow object at 0x13821c9b0>.container
 +              where <toga_iOS.window.MainWindow object at 0x13821c9b0> = <tests_backend.window.WindowProbe object at 0x13c2dfbf0>.impl
 +  and   100.33333333333334 = <tests_backend.window.WindowProbe object at 0x13c2dfbf0>.top_bar_height
---------------------------- Captured stdout setup -----------------------------
Resetting main_window
=========================== short test summary info ============================
ERROR tests/app/test_app.py::test_unsupported_widget - assert 100.33333333333331 >= 100.33333333333334
 +  where 100.33333333333331 = <NSPoint(0.0, 100.33333333333331)>.y
 +    where <NSPoint(0.0, 100.33333333333331)> = <NSRect(NSPoint(0.0, 100.33333333333331), NSSize(402.0, 773.0))>.origin
 +      where <NSRect(NSPoint(0.0, 100.33333333333331), NSSize(402.0, 773.0))> = <ObjCInstance: TogaView at 0x13c2ba8a0: <TogaView: 0x13ca0e5c0; frame = (0 100.333; 402 773); backgroundColor = UIExtendedSRGBColorSpace 0.854902 0.647059 0.12549 1; layer = <CALayer: 0x600000267700>>>.frame
 +        where <ObjCInstance: TogaView at 0x13c2ba8a0: <TogaView: 0x13ca0e5c0; frame = (0 100.333; 402 773); backgroundColor = UIExtendedSRGBColorSpace 0.854902 0.647059 0.12549 1; layer = <CALayer: 0x600000267700>>> = <toga_iOS.widgets.box.Box object at 0x13b6f4f20>.native
 +          where <toga_iOS.widgets.box.Box object at 0x13b6f4f20> = <toga_iOS.container.NavigationContainer object at 0x13a44a0c0>.content
 +            where <toga_iOS.container.NavigationContainer object at 0x13a44a0c0> = <toga_iOS.window.MainWindow object at 0x13821c9b0>.container
 +              where <toga_iOS.window.MainWindow object at 0x13821c9b0> = <tests_backend.window.WindowProbe object at 0x13c2dfbf0>.impl
 +  and   100.33333333333334 = <tests_backend.window.WindowProbe object at 0x13c2dfbf0>.top_bar_height
=============================== 1 error in 5.25s ===============================

Floating-point inaccuracy strikes again. Unfortunately, because pytest.approx intentionally doesn't support inequalities (explained by a note in the docs that I still find baffling), we can't simply write a >= approx(b); we instead need a > b or a == approx(b).

This isn't the first time I've seen an issue like this crop up; I'm starting to wonder if it would be worth writing our own subclass or helper function to handle floating-point <= / >= comparisons.

PR Checklist:

  • I will abide by the BeeWare Code of Conduct
  • I have read and have followed the CONTRIBUTING.md file
  • This PR was generated or assisted using an AI tool

@HalfWhitt HalfWhitt changed the title Account for floating-point error Account for floating-point error in iOS Window test backend Jun 25, 2026
@HalfWhitt

Copy link
Copy Markdown
Member Author

This isn't the first time I've seen an issue like this crop up; I'm starting to wonder if it would be worth writing our own subclass or helper function to handle floating-point <= / >= comparisons.

I've gone ahead and done this, and added a test to verify it behaves as expected. The definition lives in the root of the testbed tests, so it should be accessible from all testbed tests. Notably, it's not available to the core tests; if we like this approach here, it might be worth implementing it there too.

@HalfWhitt HalfWhitt changed the title Account for floating-point error in iOS Window test backend Add custom approx() to help with floating point <= / >= testing Jun 25, 2026
@HalfWhitt HalfWhitt requested a review from freakboy3742 June 25, 2026 23:40

@johnzhou721 johnzhou721 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great!! I really liked how you subclassed ApproxScalar rather than pulling your own custom class, which was what I've done in these situations in the past.

@freakboy3742 freakboy3742 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree the decision on disallowing <=/>= comparisons is... odd. I don't love the fact that we're reaching into an internal API to implement this - but it works, and we'll get plenty of warning if it ever changes/breaks.

Marking as approved; one suggestion inline tied to the pytest version compatibility thing.

Comment thread testbed/tests/conftest.py Outdated
@freakboy3742 freakboy3742 force-pushed the widen-iOS-assertion branch from 748d370 to 6087e2b Compare June 26, 2026 04:42
@freakboy3742 freakboy3742 force-pushed the widen-iOS-assertion branch from 6087e2b to cf51148 Compare June 26, 2026 04:45
@HalfWhitt HalfWhitt merged commit 5af38e2 into beeware:main Jun 26, 2026
125 of 126 checks passed
@HalfWhitt HalfWhitt deleted the widen-iOS-assertion branch June 26, 2026 05:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants