Skip to content

Commit 4658ab0

Browse files
authored
Merge pull request matplotlib#29872 from QuLogic/layout-text-placeholders
TST: Use placeholders for text in layout tests
2 parents a464694 + 3d0fd3c commit 4658ab0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+2809
-9112
lines changed

doc/devel/testing.rst

+4-3
Original file line numberDiff line numberDiff line change
@@ -163,9 +163,10 @@ the tests, they should now pass.
163163

164164
It is preferred that new tests use ``style='mpl20'`` as this leads to smaller
165165
figures and reflects the newer look of default Matplotlib plots. Also, if the
166-
texts (labels, tick labels, etc) are not really part of what is tested, use
167-
``remove_text=True`` as this will lead to smaller figures and reduce possible
168-
issues with font mismatch on different platforms.
166+
texts (labels, tick labels, etc) are not really part of what is tested, use the
167+
``remove_text=True`` argument or add the ``text_placeholders`` fixture as this
168+
will lead to smaller figures and reduce possible issues with font mismatch on
169+
different platforms.
169170

170171

171172
Compare two methods of creating an image

lib/matplotlib/testing/conftest.py

+51
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,54 @@ def test_imshow_xarray(xr):
125125

126126
xr = pytest.importorskip('xarray')
127127
return xr
128+
129+
130+
@pytest.fixture
131+
def text_placeholders(monkeypatch):
132+
"""
133+
Replace texts with placeholder rectangles.
134+
135+
The rectangle size only depends on the font size and the number of characters. It is
136+
thus insensitive to font properties and rendering details. This should be used for
137+
tests that depend on text geometries but not the actual text rendering, e.g. layout
138+
tests.
139+
"""
140+
from matplotlib.patches import Rectangle
141+
142+
def patched_get_text_metrics_with_cache(renderer, text, fontprop, ismath, dpi):
143+
"""
144+
Replace ``_get_text_metrics_with_cache`` with fixed results.
145+
146+
The usual ``renderer.get_text_width_height_descent`` would depend on font
147+
metrics; instead the fixed results are based on font size and the length of the
148+
string only.
149+
"""
150+
# While get_window_extent returns pixels and font size is in points, font size
151+
# includes ascenders and descenders. Leaving out this factor and setting
152+
# descent=0 ends up with a box that is relatively close to DejaVu Sans.
153+
height = fontprop.get_size()
154+
width = len(text) * height / 1.618 # Golden ratio for character size.
155+
descent = 0
156+
return width, height, descent
157+
158+
def patched_text_draw(self, renderer):
159+
"""
160+
Replace ``Text.draw`` with a fixed bounding box Rectangle.
161+
162+
The bounding box corresponds to ``Text.get_window_extent``, which ultimately
163+
depends on the above patched ``_get_text_metrics_with_cache``.
164+
"""
165+
if renderer is not None:
166+
self._renderer = renderer
167+
if not self.get_visible():
168+
return
169+
if self.get_text() == '':
170+
return
171+
bbox = self.get_window_extent()
172+
rect = Rectangle(bbox.p0, bbox.width, bbox.height,
173+
facecolor=self.get_color(), edgecolor='none')
174+
rect.draw(renderer)
175+
176+
monkeypatch.setattr('matplotlib.text._get_text_metrics_with_cache',
177+
patched_get_text_metrics_with_cache)
178+
monkeypatch.setattr('matplotlib.text.Text.draw', patched_text_draw)

lib/matplotlib/testing/conftest.pyi

+2
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,5 @@ def mpl_test_settings(request: pytest.FixtureRequest) -> None: ...
1010
def pd() -> ModuleType: ...
1111
@pytest.fixture
1212
def xr() -> ModuleType: ...
13+
@pytest.fixture
14+
def text_placeholders(monkeypatch: pytest.MonkeyPatch) -> None: ...
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Binary file not shown.
Loading

0 commit comments

Comments
 (0)