Skip to content

Commit 2075658

Browse files
committed
Use mocks for widget test callbacks
1 parent 27053ae commit 2075658

File tree

1 file changed

+58
-91
lines changed

1 file changed

+58
-91
lines changed

lib/matplotlib/tests/test_widgets.py

Lines changed: 58 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import functools
2+
from unittest import mock
23

34
from matplotlib._api.deprecation import MatplotlibDeprecationWarning
45
from matplotlib.backend_bases import MouseEvent
@@ -23,12 +24,7 @@ def ax():
2324
def check_rectangle(**kwargs):
2425
ax = get_ax()
2526

26-
def onselect(epress, erelease):
27-
ax._got_onselect = True
28-
assert epress.xdata == 100
29-
assert epress.ydata == 100
30-
assert erelease.xdata == 199
31-
assert erelease.ydata == 199
27+
onselect = mock.Mock(spec=noop, return_value=None)
3228

3329
tool = widgets.RectangleSelector(ax, onselect, **kwargs)
3430
do_event(tool, 'press', xdata=100, ydata=100, button=1)
@@ -43,7 +39,13 @@ def onselect(epress, erelease):
4339
[100, 199, 199, 100, 100]],
4440
err_msg=tool.geometry)
4541

46-
assert ax._got_onselect
42+
onselect.assert_called_once()
43+
(epress, erelease), kwargs = onselect.call_args
44+
assert epress.xdata == 100
45+
assert epress.ydata == 100
46+
assert erelease.xdata == 199
47+
assert erelease.ydata == 199
48+
assert kwargs == {}
4749

4850

4951
def test_rectangle_selector():
@@ -69,13 +71,8 @@ def test_rectangle_selector():
6971
@pytest.mark.parametrize('minspanx, x1', [[0, 10], [1, 10.5], [1, 11]])
7072
@pytest.mark.parametrize('minspany, y1', [[0, 10], [1, 10.5], [1, 11]])
7173
def test_rectangle_minspan(ax, spancoords, minspanx, x1, minspany, y1):
72-
# attribute to track number of onselect calls
73-
ax._n_onselect = 0
7474

75-
def onselect(epress, erelease):
76-
ax._n_onselect += 1
77-
ax._epress = epress
78-
ax._erelease = erelease
75+
onselect = mock.Mock(spec=noop, return_value=None)
7976

8077
x0, y0 = (10, 10)
8178
if spancoords == 'pixels':
@@ -88,21 +85,24 @@ def onselect(epress, erelease):
8885
# Too small to create a selector
8986
click_and_drag(tool, start=(x0, x1), end=(y0, y1))
9087
assert not tool._selection_completed
91-
assert ax._n_onselect == 0
88+
onselect.assert_not_called()
9289

9390
click_and_drag(tool, start=(20, 20), end=(30, 30))
9491
assert tool._selection_completed
95-
assert ax._n_onselect == 1
92+
onselect.assert_called_once()
9693

9794
# Too small to create a selector. Should clear existing selector, and
9895
# trigger onselect because there was a preexisting selector
96+
onselect.reset_mock()
9997
click_and_drag(tool, start=(x0, y0), end=(x1, y1))
10098
assert not tool._selection_completed
101-
assert ax._n_onselect == 2
102-
assert ax._epress.xdata == x0
103-
assert ax._epress.ydata == y0
104-
assert ax._erelease.xdata == x1
105-
assert ax._erelease.ydata == y1
99+
onselect.assert_called_once()
100+
(epress, erelease), kwargs = onselect.call_args
101+
assert epress.xdata == x0
102+
assert epress.ydata == y0
103+
assert erelease.xdata == x1
104+
assert erelease.ydata == y1
105+
assert kwargs == {}
106106

107107

108108
def test_deprecation_selector_visible_attribute():
@@ -570,62 +570,49 @@ def test_rectangle_handles(ax):
570570
@pytest.mark.parametrize('interactive', [True, False])
571571
def test_rectangle_selector_onselect(ax, interactive):
572572
# check when press and release events take place at the same position
573-
def onselect(vmin, vmax):
574-
ax._got_onselect = True
573+
onselect = mock.Mock(spec=noop, return_value=None)
575574

576575
tool = widgets.RectangleSelector(ax, onselect, interactive=interactive)
577576
# move outside of axis
578577
click_and_drag(tool, start=(100, 110), end=(150, 120))
579578

580-
assert tool.ax._got_onselect
579+
onselect.assert_called_once()
581580
assert tool.extents == (100.0, 150.0, 110.0, 120.0)
582581

583-
# Reset tool.ax._got_onselect
584-
tool.ax._got_onselect = False
582+
onselect.reset_mock()
585583
click_and_drag(tool, start=(10, 100), end=(10, 100))
586-
587-
assert tool.ax._got_onselect
584+
onselect.assert_called_once()
588585

589586

590587
@pytest.mark.parametrize('ignore_event_outside', [True, False])
591588
def test_rectangle_selector_ignore_outside(ax, ignore_event_outside):
592-
def onselect(vmin, vmax):
593-
ax._got_onselect = True
589+
onselect = mock.Mock(spec=noop, return_value=None)
594590

595591
tool = widgets.RectangleSelector(ax, onselect,
596592
ignore_event_outside=ignore_event_outside)
597593
click_and_drag(tool, start=(100, 110), end=(150, 120))
598-
assert tool.ax._got_onselect
594+
onselect.assert_called_once()
599595
assert tool.extents == (100.0, 150.0, 110.0, 120.0)
600596

601-
# Reset
602-
ax._got_onselect = False
597+
onselect.reset_mock()
603598
# Trigger event outside of span
604599
click_and_drag(tool, start=(150, 150), end=(160, 160))
605600
if ignore_event_outside:
606601
# event have been ignored and span haven't changed.
607-
assert not ax._got_onselect
602+
onselect.assert_not_called()
608603
assert tool.extents == (100.0, 150.0, 110.0, 120.0)
609604
else:
610605
# A new shape is created
611-
assert ax._got_onselect
606+
onselect.assert_called_once()
612607
assert tool.extents == (150.0, 160.0, 150.0, 160.0)
613608

614609

615-
def check_span(*args, **kwargs):
610+
def check_span(*args, onmove_callback=True, **kwargs):
616611
ax = get_ax()
617612

618-
def onselect(vmin, vmax):
619-
ax._got_onselect = True
620-
assert vmin == 100
621-
assert vmax == 199
622-
623-
def onmove(vmin, vmax):
624-
assert vmin == 100
625-
assert vmax == 199
626-
ax._got_on_move = True
627-
628-
if 'onmove_callback' in kwargs:
613+
onselect = mock.Mock(spec=noop, return_value=None)
614+
onmove = mock.Mock(spec=noop, return_value=None)
615+
if onmove_callback:
629616
kwargs['onmove_callback'] = onmove
630617

631618
tool = widgets.SpanSelector(ax, onselect, *args, **kwargs)
@@ -634,10 +621,9 @@ def onmove(vmin, vmax):
634621
do_event(tool, 'onmove', xdata=199, ydata=199, button=1)
635622
do_event(tool, 'release', xdata=250, ydata=250, button=1)
636623

637-
assert ax._got_onselect
638-
639-
if 'onmove_callback' in kwargs:
640-
assert ax._got_on_move
624+
onselect.assert_called_once_with(100, 199)
625+
if onmove_callback:
626+
onmove.assert_called_once_with(100, 199)
641627

642628

643629
def test_span_selector():
@@ -649,52 +635,46 @@ def test_span_selector():
649635

650636
@pytest.mark.parametrize('interactive', [True, False])
651637
def test_span_selector_onselect(ax, interactive):
652-
def onselect(vmin, vmax):
653-
ax._got_onselect = True
638+
onselect = mock.Mock(spec=noop, return_value=None)
654639

655640
tool = widgets.SpanSelector(ax, onselect, 'horizontal',
656641
interactive=interactive)
657642
# move outside of axis
658643
click_and_drag(tool, start=(100, 100), end=(150, 100))
659-
assert tool.ax._got_onselect
644+
onselect.assert_called_once()
660645
assert tool.extents == (100, 150)
661646

662-
# Reset tool.ax._got_onselect
663-
tool.ax._got_onselect = False
647+
onselect.reset_mock()
664648
click_and_drag(tool, start=(10, 100), end=(10, 100))
665-
assert tool.ax._got_onselect
649+
onselect.assert_called_once()
666650

667651

668652
@pytest.mark.parametrize('ignore_event_outside', [True, False])
669653
def test_span_selector_ignore_outside(ax, ignore_event_outside):
670-
def onselect(vmin, vmax):
671-
ax._got_onselect = True
672-
673-
def onmove(vmin, vmax):
674-
ax._got_on_move = True
654+
onselect = mock.Mock(spec=noop, return_value=None)
655+
onmove = mock.Mock(spec=noop, return_value=None)
675656

676657
tool = widgets.SpanSelector(ax, onselect, 'horizontal',
677658
onmove_callback=onmove,
678659
ignore_event_outside=ignore_event_outside)
679660
click_and_drag(tool, start=(100, 100), end=(125, 125))
680-
assert ax._got_onselect
681-
assert ax._got_on_move
661+
onselect.assert_called_once()
662+
onmove.assert_called_once()
682663
assert tool.extents == (100, 125)
683664

684-
# Reset
685-
ax._got_onselect = False
686-
ax._got_on_move = False
665+
onselect.reset_mock()
666+
onmove.reset_mock()
687667
# Trigger event outside of span
688668
click_and_drag(tool, start=(150, 150), end=(160, 160))
689669
if ignore_event_outside:
690670
# event have been ignored and span haven't changed.
691-
assert not ax._got_onselect
692-
assert not ax._got_on_move
671+
onselect.assert_not_called()
672+
onmove.assert_not_called()
693673
assert tool.extents == (100, 125)
694674
else:
695675
# A new shape is created
696-
assert ax._got_onselect
697-
assert ax._got_on_move
676+
onselect.assert_called_once()
677+
onmove.assert_called_once()
698678
assert tool.extents == (150, 160)
699679

700680

@@ -971,16 +951,14 @@ def onselect(vmin, vmax):
971951
def check_lasso_selector(**kwargs):
972952
ax = get_ax()
973953

974-
def onselect(verts):
975-
ax._got_onselect = True
976-
assert verts == [(100, 100), (125, 125), (150, 150)]
954+
onselect = mock.Mock(spec=noop, return_value=None)
977955

978956
tool = widgets.LassoSelector(ax, onselect, **kwargs)
979957
do_event(tool, 'press', xdata=100, ydata=100, button=1)
980958
do_event(tool, 'onmove', xdata=125, ydata=125, button=1)
981959
do_event(tool, 'release', xdata=150, ydata=150, button=1)
982960

983-
assert ax._got_onselect
961+
onselect.assert_called_once_with([(100, 100), (125, 125), (150, 150)])
984962

985963

986964
def test_lasso_selector():
@@ -1004,9 +982,8 @@ def test_TextBox(ax, toolbar):
1004982
# Avoid "toolmanager is provisional" warning.
1005983
dict.__setitem__(plt.rcParams, "toolbar", toolbar)
1006984

1007-
from unittest.mock import Mock
1008-
submit_event = Mock()
1009-
text_change_event = Mock()
985+
submit_event = mock.Mock(spec=noop, return_value=None)
986+
text_change_event = mock.Mock(spec=noop, return_value=None)
1010987
tool = widgets.TextBox(ax, '')
1011988
tool.on_submit(submit_event)
1012989
tool.on_text_change(text_change_event)
@@ -1215,19 +1192,15 @@ def check_polygon_selector(event_sequence, expected_result, selections_count,
12151192
"""
12161193
ax = get_ax()
12171194

1218-
ax._selections_count = 0
1219-
1220-
def onselect(vertices):
1221-
ax._selections_count += 1
1222-
ax._current_result = vertices
1195+
onselect = mock.Mock(spec=noop, return_value=None)
12231196

12241197
tool = widgets.PolygonSelector(ax, onselect, **kwargs)
12251198

12261199
for (etype, event_args) in event_sequence:
12271200
do_event(tool, etype, **event_args)
12281201

1229-
assert ax._selections_count == selections_count
1230-
assert ax._current_result == expected_result
1202+
assert onselect.call_count == selections_count
1203+
assert onselect.call_args == ((expected_result, ), {})
12311204

12321205

12331206
def polygon_place_vertex(xdata, ydata):
@@ -1358,13 +1331,7 @@ def test_polygon_selector(draw_bounding_box):
13581331

13591332
@pytest.mark.parametrize('draw_bounding_box', [False, True])
13601333
def test_polygon_selector_set_props_handle_props(ax, draw_bounding_box):
1361-
ax._selections_count = 0
1362-
1363-
def onselect(vertices):
1364-
ax._selections_count += 1
1365-
ax._current_result = vertices
1366-
1367-
tool = widgets.PolygonSelector(ax, onselect,
1334+
tool = widgets.PolygonSelector(ax, onselect=noop,
13681335
props=dict(color='b', alpha=0.2),
13691336
handle_props=dict(alpha=0.5),
13701337
draw_bounding_box=draw_bounding_box)

0 commit comments

Comments
 (0)