Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8fa61a4

Browse files
authored
Merge pull request #18501 from larsoner/test
TST: Add test for _repr_html_
2 parents 7ded0f2 + b4fd83c commit 8fa61a4

File tree

1 file changed

+80
-51
lines changed

1 file changed

+80
-51
lines changed

lib/matplotlib/tests/test_animation.py

Lines changed: 80 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,33 @@
1313
from matplotlib import animation
1414

1515

16+
@pytest.fixture()
17+
def anim(request):
18+
"""Create a simple animation (with options)."""
19+
fig, ax = plt.subplots()
20+
line, = ax.plot([], [])
21+
22+
ax.set_xlim(0, 10)
23+
ax.set_ylim(-1, 1)
24+
25+
def init():
26+
line.set_data([], [])
27+
return line,
28+
29+
def animate(i):
30+
x = np.linspace(0, 10, 100)
31+
y = np.sin(x + i)
32+
line.set_data(x, y)
33+
return line,
34+
35+
# "klass" can be passed to determine the class returned by the fixture
36+
kwargs = dict(getattr(request, 'param', {})) # make a copy
37+
klass = kwargs.pop('klass', animation.FuncAnimation)
38+
if 'frames' not in kwargs:
39+
kwargs['frames'] = 5
40+
return klass(fig=fig, func=animate, init_func=init, **kwargs)
41+
42+
1643
class NullMovieWriter(animation.AbstractMovieWriter):
1744
"""
1845
A minimal MovieWriter. It doesn't actually write anything.
@@ -40,26 +67,8 @@ def finish(self):
4067
pass
4168

4269

43-
def make_animation(**kwargs):
44-
fig, ax = plt.subplots()
45-
line, = ax.plot([])
46-
47-
def init():
48-
pass
49-
50-
def animate(i):
51-
line.set_data([0, 1], [0, i])
52-
return line,
53-
54-
return animation.FuncAnimation(fig, animate, **kwargs)
55-
56-
57-
def test_null_movie_writer():
70+
def test_null_movie_writer(anim):
5871
# Test running an animation with NullMovieWriter.
59-
60-
num_frames = 5
61-
anim = make_animation(frames=num_frames)
62-
6372
filename = "unused.null"
6473
dpi = 50
6574
savefig_kwargs = dict(foo=0)
@@ -68,17 +77,17 @@ def test_null_movie_writer():
6877
anim.save(filename, dpi=dpi, writer=writer,
6978
savefig_kwargs=savefig_kwargs)
7079

71-
assert writer.fig == plt.figure(1) # The figure used by make_animation.
80+
assert writer.fig == plt.figure(1) # The figure used by anim fixture
7281
assert writer.outfile == filename
7382
assert writer.dpi == dpi
7483
assert writer.args == ()
7584
assert writer.savefig_kwargs == savefig_kwargs
76-
assert writer._count == num_frames
77-
85+
assert writer._count == anim.save_count
7886

79-
def test_animation_delete():
80-
anim = make_animation(frames=5)
8187

88+
@pytest.mark.parametrize('anim', [dict(klass=dict)], indirect=['anim'])
89+
def test_animation_delete(anim):
90+
anim = animation.FuncAnimation(**anim)
8291
with pytest.warns(Warning, match='Animation was deleted'):
8392
del anim
8493
gc.collect()
@@ -140,44 +149,62 @@ def isAvailable(cls):
140149
# design more sophisticated tests which compare resulting frames a-la
141150
# matplotlib.testing.image_comparison
142151
@pytest.mark.parametrize('writer, output', WRITER_OUTPUT)
143-
def test_save_animation_smoketest(tmpdir, writer, output):
152+
@pytest.mark.parametrize('anim', [dict(klass=dict)], indirect=['anim'])
153+
def test_save_animation_smoketest(tmpdir, writer, output, anim):
144154
if not animation.writers.is_available(writer):
145155
pytest.skip("writer '%s' not available on this system" % writer)
146-
fig, ax = plt.subplots()
147-
line, = ax.plot([], [])
148-
149-
ax.set_xlim(0, 10)
150-
ax.set_ylim(-1, 1)
151156

157+
anim = animation.FuncAnimation(**anim)
152158
dpi = None
153159
codec = None
154160
if writer == 'ffmpeg':
155161
# Issue #8253
156-
fig.set_size_inches((10.85, 9.21))
162+
anim._fig.set_size_inches((10.85, 9.21))
157163
dpi = 100.
158164
codec = 'h264'
159165

160-
def init():
161-
line.set_data([], [])
162-
return line,
163-
164-
def animate(i):
165-
x = np.linspace(0, 10, 100)
166-
y = np.sin(x + i)
167-
line.set_data(x, y)
168-
return line,
169-
170166
# Use temporary directory for the file-based writers, which produce a file
171167
# per frame with known names.
172168
with tmpdir.as_cwd():
173-
anim = animation.FuncAnimation(fig, animate, init_func=init, frames=5)
174169
anim.save(output, fps=30, writer=writer, bitrate=500, dpi=dpi,
175170
codec=codec)
171+
with pytest.warns(None):
172+
del anim
176173

177174

178-
def test_no_length_frames():
179-
(make_animation(frames=iter(range(5)))
180-
.save('unused.null', writer=NullMovieWriter()))
175+
@pytest.mark.parametrize('writer', [
176+
pytest.param(
177+
'ffmpeg', marks=pytest.mark.skipif(
178+
not animation.FFMpegWriter.isAvailable(),
179+
reason='Requires FFMpeg')),
180+
pytest.param(
181+
'imagemagick', marks=pytest.mark.skipif(
182+
not animation.ImageMagickWriter.isAvailable(),
183+
reason='Requires ImageMagick')),
184+
])
185+
@pytest.mark.parametrize('html, want', [
186+
('none', None),
187+
('html5', '<video width'),
188+
('jshtml', '<script ')
189+
])
190+
@pytest.mark.parametrize('anim', [dict(klass=dict)], indirect=['anim'])
191+
def test_animation_repr_html(writer, html, want, anim):
192+
# create here rather than in the fixture otherwise we get __del__ warnings
193+
# about producing no output
194+
anim = animation.FuncAnimation(**anim)
195+
with plt.rc_context({'animation.writer': writer,
196+
'animation.html': html}):
197+
html = anim._repr_html_()
198+
if want is None:
199+
assert html is None
200+
else:
201+
assert want in html
202+
203+
204+
@pytest.mark.parametrize('anim', [dict(frames=iter(range(5)))],
205+
indirect=['anim'])
206+
def test_no_length_frames(anim):
207+
anim.save('unused.null', writer=NullMovieWriter())
181208

182209

183210
def test_movie_writer_registry():
@@ -196,11 +223,12 @@ def test_movie_writer_registry():
196223
not animation.writers.is_available(mpl.rcParams["animation.writer"]),
197224
reason="animation writer not installed")),
198225
"to_jshtml"])
199-
def test_embed_limit(method_name, caplog, tmpdir):
226+
@pytest.mark.parametrize('anim', [dict(frames=1)], indirect=['anim'])
227+
def test_embed_limit(method_name, caplog, tmpdir, anim):
200228
caplog.set_level("WARNING")
201229
with tmpdir.as_cwd():
202230
with mpl.rc_context({"animation.embed_limit": 1e-6}): # ~1 byte.
203-
getattr(make_animation(frames=1), method_name)()
231+
getattr(anim, method_name)()
204232
assert len(caplog.records) == 1
205233
record, = caplog.records
206234
assert (record.name == "matplotlib.animation"
@@ -213,14 +241,15 @@ def test_embed_limit(method_name, caplog, tmpdir):
213241
not animation.writers.is_available(mpl.rcParams["animation.writer"]),
214242
reason="animation writer not installed")),
215243
"to_jshtml"])
216-
def test_cleanup_temporaries(method_name, tmpdir):
244+
@pytest.mark.parametrize('anim', [dict(frames=1)], indirect=['anim'])
245+
def test_cleanup_temporaries(method_name, tmpdir, anim):
217246
with tmpdir.as_cwd():
218-
getattr(make_animation(frames=1), method_name)()
247+
getattr(anim, method_name)()
219248
assert list(Path(str(tmpdir)).iterdir()) == []
220249

221250

222251
@pytest.mark.skipif(os.name != "posix", reason="requires a POSIX OS")
223-
def test_failing_ffmpeg(tmpdir, monkeypatch):
252+
def test_failing_ffmpeg(tmpdir, monkeypatch, anim):
224253
"""
225254
Test that we correctly raise a CalledProcessError when ffmpeg fails.
226255
@@ -235,7 +264,7 @@ def test_failing_ffmpeg(tmpdir, monkeypatch):
235264
"[[ $@ -eq 0 ]]\n")
236265
os.chmod(str(exe_path), 0o755)
237266
with pytest.raises(subprocess.CalledProcessError):
238-
make_animation().save("test.mpeg")
267+
anim.save("test.mpeg")
239268

240269

241270
@pytest.mark.parametrize("cache_frame_data", [False, True])

0 commit comments

Comments
 (0)