From 926e962b6e9ba507c1ddceda83e00f71a1e37fa5 Mon Sep 17 00:00:00 2001 From: JasonGrace2282 Date: Fri, 12 Jul 2024 14:15:40 -0400 Subject: [PATCH] Change tests to use the config fixture --- tests/helpers/graphical_units.py | 6 +- tests/module/animation/test_animation.py | 4 +- tests/module/animation/test_creation.py | 4 +- tests/module/mobject/mobject/test_copy.py | 4 +- .../mobject/mobject/test_opengl_metaclass.py | 16 +- tests/module/mobject/mobject/test_set_attr.py | 7 +- tests/module/mobject/text/test_texmobject.py | 32 +-- tests/module/scene/test_scene.py | 172 ++++++----- tests/module/utils/test_units.py | 6 +- tests/opengl/test_config_opengl.py | 113 ++++---- tests/opengl/test_copy_opengl.py | 4 +- tests/opengl/test_ipython_magic_opengl.py | 39 ++- tests/opengl/test_texmobject_opengl.py | 8 +- tests/test_config.py | 270 +++++++++--------- tests/test_ipython_magic.py | 33 ++- .../opengl/test_opengl_renderer.py | 23 +- .../opengl/test_play_logic_opengl.py | 15 +- tests/test_scene_rendering/simple_scenes.py | 15 + tests/test_scene_rendering/test_play_logic.py | 18 +- 19 files changed, 396 insertions(+), 393 deletions(-) diff --git a/tests/helpers/graphical_units.py b/tests/helpers/graphical_units.py index 75fb00343a..01eae516a9 100644 --- a/tests/helpers/graphical_units.py +++ b/tests/helpers/graphical_units.py @@ -7,11 +7,11 @@ import numpy as np -from manim import config, logger +from manim import logger from manim.scene.scene import Scene -def set_test_scene(scene_object: type[Scene], module_name: str): +def set_test_scene(scene_object: type[Scene], module_name: str, config): """Function used to set up the test data for a new feature. This will basically set up a pre-rendered frame for a scene. This is meant to be used only when setting up tests. Please refer to the wiki. @@ -46,7 +46,7 @@ def set_test_scene(scene_object: type[Scene], module_name: str): assert not np.all( data == np.array([0, 0, 0, 255]), - ), f"Control data generated for {str(scene)} only contains empty pixels." + ), f"Control data generated for {scene!s} only contains empty pixels." assert data.shape == (480, 854, 4) tests_directory = Path(__file__).absolute().parent.parent path_control_data = Path(tests_directory) / "control_data" / "graphical_units_data" diff --git a/tests/module/animation/test_animation.py b/tests/module/animation/test_animation.py index 67579c4fbf..d57f57247e 100644 --- a/tests/module/animation/test_animation.py +++ b/tests/module/animation/test_animation.py @@ -2,7 +2,7 @@ import pytest -from manim import FadeIn, Scene, config +from manim import FadeIn, Scene @pytest.mark.parametrize( @@ -15,7 +15,7 @@ def test_animation_forbidden_run_time(run_time): test_scene.play(FadeIn(None, run_time=run_time)) -def test_animation_run_time_shorter_than_frame_rate(caplog): +def test_animation_run_time_shorter_than_frame_rate(caplog, config): test_scene = Scene() test_scene.play(FadeIn(None, run_time=1 / (config.frame_rate + 1))) assert ( diff --git a/tests/module/animation/test_creation.py b/tests/module/animation/test_creation.py index 3208ad1b41..d2a0b08666 100644 --- a/tests/module/animation/test_creation.py +++ b/tests/module/animation/test_creation.py @@ -3,7 +3,7 @@ import numpy as np import pytest -from manim import AddTextLetterByLetter, Text, config +from manim import AddTextLetterByLetter, Text def test_non_empty_text_creation(): @@ -25,7 +25,7 @@ def test_whitespace_text_creation(): AddTextLetterByLetter(Text(" ")) -def test_run_time_for_non_empty_text(): +def test_run_time_for_non_empty_text(config): """Ensure the run_time is calculated correctly for non-empty text.""" s = Text("Hello") run_time_per_char = 0.1 diff --git a/tests/module/mobject/mobject/test_copy.py b/tests/module/mobject/mobject/test_copy.py index ce9f472f7e..39c6afd94c 100644 --- a/tests/module/mobject/mobject/test_copy.py +++ b/tests/module/mobject/mobject/test_copy.py @@ -2,7 +2,7 @@ from pathlib import Path -from manim import BraceLabel, Mobject, config +from manim import BraceLabel, Mobject def test_mobject_copy(): @@ -18,7 +18,7 @@ def test_mobject_copy(): assert orig.submobjects[i] is not copy.submobjects[i] -def test_bracelabel_copy(tmp_path): +def test_bracelabel_copy(tmp_path, config): """Test that a copy is a deepcopy.""" # For this test to work, we need to tweak some folders temporarily original_text_dir = config["text_dir"] diff --git a/tests/module/mobject/mobject/test_opengl_metaclass.py b/tests/module/mobject/mobject/test_opengl_metaclass.py index bc172bfa38..930a5616da 100644 --- a/tests/module/mobject/mobject/test_opengl_metaclass.py +++ b/tests/module/mobject/mobject/test_opengl_metaclass.py @@ -1,20 +1,20 @@ from __future__ import annotations -from manim import Mobject, config, tempconfig +from manim import Mobject from manim.mobject.opengl.opengl_compatibility import ConvertToOpenGL from manim.mobject.opengl.opengl_mobject import OpenGLMobject -def test_metaclass_registry(): +def test_metaclass_registry(config): class SomeTestMobject(Mobject, metaclass=ConvertToOpenGL): pass assert SomeTestMobject in ConvertToOpenGL._converted_classes - with tempconfig({"renderer": "opengl"}): - assert OpenGLMobject in SomeTestMobject.__bases__ - assert Mobject not in SomeTestMobject.__bases__ + config.renderer = "opengl" + assert OpenGLMobject in SomeTestMobject.__bases__ + assert Mobject not in SomeTestMobject.__bases__ - config.renderer = "cairo" - assert Mobject in SomeTestMobject.__bases__ - assert OpenGLMobject not in SomeTestMobject.__bases__ + config.renderer = "cairo" + assert Mobject in SomeTestMobject.__bases__ + assert OpenGLMobject not in SomeTestMobject.__bases__ diff --git a/tests/module/mobject/mobject/test_set_attr.py b/tests/module/mobject/mobject/test_set_attr.py index f9cdd40fe6..9edfb93bc4 100644 --- a/tests/module/mobject/mobject/test_set_attr.py +++ b/tests/module/mobject/mobject/test_set_attr.py @@ -2,13 +2,11 @@ import numpy as np -from manim import RendererType, config from manim.constants import RIGHT from manim.mobject.geometry.polygram import Square -def test_Data(): - config.renderer = RendererType.OPENGL +def test_Data(using_opengl_renderer): a = Square().move_to(RIGHT) data_bb = a.data["bounding_box"] np.testing.assert_array_equal( @@ -39,6 +37,3 @@ def test_Data(): ) np.testing.assert_array_equal(a.bounding_box, data_bb) - config.renderer = ( - RendererType.CAIRO - ) # needs to be here or else the following cairo tests fail diff --git a/tests/module/mobject/text/test_texmobject.py b/tests/module/mobject/text/test_texmobject.py index c8d4f51f84..52cc1554cc 100644 --- a/tests/module/mobject/text/test_texmobject.py +++ b/tests/module/mobject/text/test_texmobject.py @@ -5,15 +5,15 @@ import numpy as np import pytest -from manim import MathTex, SingleStringMathTex, Tex, TexTemplate, config, tempconfig +from manim import MathTex, SingleStringMathTex, Tex, TexTemplate, tempconfig -def test_MathTex(): +def test_MathTex(config): MathTex("a^2 + b^2 = c^2") assert Path(config.media_dir, "Tex", "e4be163a00cf424f.svg").exists() -def test_SingleStringMathTex(): +def test_SingleStringMathTex(config): SingleStringMathTex("test") assert Path(config.media_dir, "Tex", "8ce17c7f5013209f.svg").exists() @@ -27,7 +27,7 @@ def test_double_braces_testing(text_input, length_sub): assert len(t1.submobjects) == length_sub -def test_tex(): +def test_tex(config): Tex("The horse does not eat cucumber salad.") assert Path(config.media_dir, "Tex", "c3945e23e546c95a.svg").exists() @@ -45,7 +45,7 @@ def test_tex_temp_directory(tmpdir, monkeypatch): assert Path("media", "Tex", "c3945e23e546c95a.svg").exists() -def test_percent_char_rendering(): +def test_percent_char_rendering(config): Tex(r"\%") assert Path(config.media_dir, "Tex", "4a583af4d19a3adf.tex").exists() @@ -194,7 +194,7 @@ def test_error_in_nested_context(capsys): \end{align} """ - with pytest.raises(ValueError) as err: + with pytest.raises(ValueError): Tex(invalid_tex) stdout = str(capsys.readouterr().out) @@ -202,25 +202,25 @@ def test_error_in_nested_context(capsys): assert r"\begin{frame}" not in stdout -def test_tempconfig_resetting_tex_template(): +def test_tempconfig_resetting_tex_template(config): my_template = TexTemplate() my_template.preamble = "Custom preamble!" - tex_template_config_value = config.tex_template with tempconfig({"tex_template": my_template}): assert config.tex_template.preamble == "Custom preamble!" assert config.tex_template.preamble != "Custom preamble!" -def test_tex_garbage_collection(tmpdir, monkeypatch): +def test_tex_garbage_collection(tmpdir, monkeypatch, config): monkeypatch.chdir(tmpdir) Path(tmpdir, "media").mkdir() + config.media_dir = "media" - with tempconfig({"media_dir": "media"}): - tex_without_log = Tex("Hello World!") # d771330b76d29ffb.tex - assert Path("media", "Tex", "d771330b76d29ffb.tex").exists() - assert not Path("media", "Tex", "d771330b76d29ffb.log").exists() + tex_without_log = Tex("Hello World!") # d771330b76d29ffb.tex + assert Path("media", "Tex", "d771330b76d29ffb.tex").exists() + assert not Path("media", "Tex", "d771330b76d29ffb.log").exists() + + config.no_latex_cleanup = True - with tempconfig({"media_dir": "media", "no_latex_cleanup": True}): - tex_with_log = Tex("Hello World, again!") # da27670a37b08799.tex - assert Path("media", "Tex", "da27670a37b08799.log").exists() + tex_with_log = Tex("Hello World, again!") # da27670a37b08799.tex + assert Path("media", "Tex", "da27670a37b08799.log").exists() diff --git a/tests/module/scene/test_scene.py b/tests/module/scene/test_scene.py index 0790b7ece6..6c3240980b 100644 --- a/tests/module/scene/test_scene.py +++ b/tests/module/scene/test_scene.py @@ -4,104 +4,100 @@ import pytest -from manim import Circle, FadeIn, Group, Mobject, Scene, Square, tempconfig +from manim import Circle, FadeIn, Group, Mobject, Scene, Square from manim.animation.animation import Wait -def test_scene_add_remove(): - with tempconfig({"dry_run": True}): - scene = Scene() - assert len(scene.mobjects) == 0 - scene.add(Mobject()) - assert len(scene.mobjects) == 1 - scene.add(*(Mobject() for _ in range(10))) - assert len(scene.mobjects) == 11 - - # Check that adding a mobject twice does not actually add it twice - repeated = Mobject() - scene.add(repeated) - assert len(scene.mobjects) == 12 - scene.add(repeated) - assert len(scene.mobjects) == 12 - - # Check that Scene.add() returns the Scene (for chained calls) - assert scene.add(Mobject()) is scene - to_remove = Mobject() - scene = Scene() - scene.add(to_remove) - scene.add(*(Mobject() for _ in range(10))) - assert len(scene.mobjects) == 11 - scene.remove(to_remove) - assert len(scene.mobjects) == 10 - scene.remove(to_remove) - assert len(scene.mobjects) == 10 - - # Check that Scene.remove() returns the instance (for chained calls) - assert scene.add(Mobject()) is scene - - -def test_scene_time(): - with tempconfig({"dry_run": True}): - scene = Scene() - assert scene.renderer.time == 0 - scene.wait(2) - assert scene.renderer.time == 2 - scene.play(FadeIn(Circle()), run_time=0.5) - assert pytest.approx(scene.renderer.time) == 2.5 - scene.renderer._original_skipping_status = True - scene.play(FadeIn(Square()), run_time=5) # this animation gets skipped. - assert pytest.approx(scene.renderer.time) == 7.5 - - -def test_subcaption(): - with tempconfig({"dry_run": True}): - scene = Scene() - scene.add_subcaption("Testing add_subcaption", duration=1, offset=0) - scene.wait() - scene.play( - Wait(), - run_time=2, - subcaption="Testing Scene.play subcaption interface", - subcaption_duration=1.5, - subcaption_offset=0.5, - ) - subcaptions = scene.renderer.file_writer.subcaptions - assert len(subcaptions) == 2 - assert subcaptions[0].start == datetime.timedelta(seconds=0) - assert subcaptions[0].end == datetime.timedelta(seconds=1) - assert subcaptions[0].content == "Testing add_subcaption" - assert subcaptions[1].start == datetime.timedelta(seconds=1.5) - assert subcaptions[1].end == datetime.timedelta(seconds=3) - assert subcaptions[1].content == "Testing Scene.play subcaption interface" - - -def test_replace(): +def test_scene_add_remove(dry_run): + scene = Scene() + assert len(scene.mobjects) == 0 + scene.add(Mobject()) + assert len(scene.mobjects) == 1 + scene.add(*(Mobject() for _ in range(10))) + assert len(scene.mobjects) == 11 + + # Check that adding a mobject twice does not actually add it twice + repeated = Mobject() + scene.add(repeated) + assert len(scene.mobjects) == 12 + scene.add(repeated) + assert len(scene.mobjects) == 12 + + # Check that Scene.add() returns the Scene (for chained calls) + assert scene.add(Mobject()) is scene + to_remove = Mobject() + scene = Scene() + scene.add(to_remove) + scene.add(*(Mobject() for _ in range(10))) + assert len(scene.mobjects) == 11 + scene.remove(to_remove) + assert len(scene.mobjects) == 10 + scene.remove(to_remove) + assert len(scene.mobjects) == 10 + + # Check that Scene.remove() returns the instance (for chained calls) + assert scene.add(Mobject()) is scene + + +def test_scene_time(dry_run): + scene = Scene() + assert scene.renderer.time == 0 + scene.wait(2) + assert scene.renderer.time == 2 + scene.play(FadeIn(Circle()), run_time=0.5) + assert pytest.approx(scene.renderer.time) == 2.5 + scene.renderer._original_skipping_status = True + scene.play(FadeIn(Square()), run_time=5) # this animation gets skipped. + assert pytest.approx(scene.renderer.time) == 7.5 + + +def test_subcaption(dry_run): + scene = Scene() + scene.add_subcaption("Testing add_subcaption", duration=1, offset=0) + scene.wait() + scene.play( + Wait(), + run_time=2, + subcaption="Testing Scene.play subcaption interface", + subcaption_duration=1.5, + subcaption_offset=0.5, + ) + subcaptions = scene.renderer.file_writer.subcaptions + assert len(subcaptions) == 2 + assert subcaptions[0].start == datetime.timedelta(seconds=0) + assert subcaptions[0].end == datetime.timedelta(seconds=1) + assert subcaptions[0].content == "Testing add_subcaption" + assert subcaptions[1].start == datetime.timedelta(seconds=1.5) + assert subcaptions[1].end == datetime.timedelta(seconds=3) + assert subcaptions[1].content == "Testing Scene.play subcaption interface" + + +def test_replace(dry_run): def assert_names(mobjs, names): assert len(mobjs) == len(names) for i in range(0, len(mobjs)): assert mobjs[i].name == names[i] - with tempconfig({"dry_run": True}): - scene = Scene() + scene = Scene() - first = Mobject(name="first") - second = Mobject(name="second") - third = Mobject(name="third") - fourth = Mobject(name="fourth") + first = Mobject(name="first") + second = Mobject(name="second") + third = Mobject(name="third") + fourth = Mobject(name="fourth") - scene.add(first) - scene.add(Group(second, third, name="group")) - scene.add(fourth) - assert_names(scene.mobjects, ["first", "group", "fourth"]) - assert_names(scene.mobjects[1], ["second", "third"]) + scene.add(first) + scene.add(Group(second, third, name="group")) + scene.add(fourth) + assert_names(scene.mobjects, ["first", "group", "fourth"]) + assert_names(scene.mobjects[1], ["second", "third"]) - alpha = Mobject(name="alpha") - beta = Mobject(name="beta") + alpha = Mobject(name="alpha") + beta = Mobject(name="beta") - scene.replace(first, alpha) - assert_names(scene.mobjects, ["alpha", "group", "fourth"]) - assert_names(scene.mobjects[1], ["second", "third"]) + scene.replace(first, alpha) + assert_names(scene.mobjects, ["alpha", "group", "fourth"]) + assert_names(scene.mobjects[1], ["second", "third"]) - scene.replace(second, beta) - assert_names(scene.mobjects, ["alpha", "group", "fourth"]) - assert_names(scene.mobjects[1], ["beta", "third"]) + scene.replace(second, beta) + assert_names(scene.mobjects, ["alpha", "group", "fourth"]) + assert_names(scene.mobjects[1], ["beta", "third"]) diff --git a/tests/module/utils/test_units.py b/tests/module/utils/test_units.py index 6c2cba1ac1..5f2995e626 100644 --- a/tests/module/utils/test_units.py +++ b/tests/module/utils/test_units.py @@ -3,13 +3,13 @@ import numpy as np import pytest -from manim import PI, X_AXIS, Y_AXIS, Z_AXIS, config +from manim import PI, X_AXIS, Y_AXIS, Z_AXIS from manim.utils.unit import Degrees, Munits, Percent, Pixels -def test_units(): +def test_units(config): # make sure we are using the right frame geometry - assert config.pixel_width == 1920 + config.pixel_width = 1920 np.testing.assert_allclose(config.frame_height, 8.0) diff --git a/tests/opengl/test_config_opengl.py b/tests/opengl/test_config_opengl.py index 378ba33558..e0dea461f6 100644 --- a/tests/opengl/test_config_opengl.py +++ b/tests/opengl/test_config_opengl.py @@ -5,10 +5,10 @@ import numpy as np -from manim import WHITE, Scene, Square, config, tempconfig +from manim import WHITE, Scene, Square, tempconfig -def test_tempconfig(using_opengl_renderer): +def test_tempconfig(config, using_opengl_renderer): """Test the tempconfig context manager.""" original = config.copy() @@ -37,35 +37,36 @@ def construct(self): self.wait(1) -def test_background_color(using_opengl_renderer): +def test_background_color(config, using_opengl_renderer, dry_run): """Test the 'background_color' config option.""" - with tempconfig({"background_color": WHITE, "verbosity": "ERROR", "dry_run": True}): - scene = MyScene() - scene.render() - frame = scene.renderer.get_frame() - np.testing.assert_allclose(frame[0, 0], [255, 255, 255, 255]) + config.background_color = WHITE + config.verbose = "ERROR" + scene = MyScene() + scene.render() + frame = scene.renderer.get_frame() + np.testing.assert_allclose(frame[0, 0], [255, 255, 255, 255]) -def test_digest_file(using_opengl_renderer, tmp_path): + +def test_digest_file(config, using_opengl_renderer, tmp_path): """Test that a config file can be digested programmatically.""" - with tempconfig({}): - tmp_cfg = tempfile.NamedTemporaryFile("w", dir=tmp_path, delete=False) - tmp_cfg.write( - """ - [CLI] - media_dir = this_is_my_favorite_path - video_dir = {media_dir}/videos - frame_height = 10 - """, - ) - tmp_cfg.close() - config.digest_file(tmp_cfg.name) + tmp_cfg = tempfile.NamedTemporaryFile("w", dir=tmp_path, delete=False) + tmp_cfg.write( + """ + [CLI] + media_dir = this_is_my_favorite_path + video_dir = {media_dir}/videos + frame_height = 10 + """, + ) + tmp_cfg.close() + config.digest_file(tmp_cfg.name) - assert config.get_dir("media_dir") == Path("this_is_my_favorite_path") - assert config.get_dir("video_dir") == Path("this_is_my_favorite_path/videos") + assert config.get_dir("media_dir") == Path("this_is_my_favorite_path") + assert config.get_dir("video_dir") == Path("this_is_my_favorite_path/videos") -def test_frame_size(using_opengl_renderer, tmp_path): +def test_frame_size(config, using_opengl_renderer, tmp_path): """Test that the frame size can be set via config file.""" np.testing.assert_allclose( config.aspect_ratio, config.pixel_width / config.pixel_height @@ -90,27 +91,28 @@ def test_frame_size(using_opengl_renderer, tmp_path): np.testing.assert_allclose(config.frame_height, 8.0) np.testing.assert_allclose(config.frame_width, 8.0) - with tempconfig({}): - tmp_cfg = tempfile.NamedTemporaryFile("w", dir=tmp_path, delete=False) - tmp_cfg.write( - """ - [CLI] - pixel_height = 10 - pixel_width = 10 - frame_height = 10 - frame_width = 10 - """, - ) - tmp_cfg.close() - config.digest_file(tmp_cfg.name) - np.testing.assert_allclose(config.aspect_ratio, 1.0) - # if both are specified in the cfg file, the aspect ratio is ignored - np.testing.assert_allclose(config.frame_height, 10.0) - np.testing.assert_allclose(config.frame_width, 10.0) +def test_frame_size_if_frame_width(config, using_opengl_renderer, tmp_path): + tmp_cfg = tempfile.NamedTemporaryFile("w", dir=tmp_path, delete=False) + tmp_cfg.write( + """ + [CLI] + pixel_height = 10 + pixel_width = 10 + frame_height = 10 + frame_width = 10 + """, + ) + tmp_cfg.close() + config.digest_file(tmp_cfg.name) + + np.testing.assert_allclose(config.aspect_ratio, 1.0) + # if both are specified in the cfg file, the aspect ratio is ignored + np.testing.assert_allclose(config.frame_height, 10.0) + np.testing.assert_allclose(config.frame_width, 10.0) -def test_temporary_dry_run(using_opengl_renderer): +def test_temporary_dry_run(config, using_opengl_renderer): """Test that tempconfig correctly restores after setting dry_run.""" assert config["write_to_movie"] assert not config["save_last_frame"] @@ -123,21 +125,20 @@ def test_temporary_dry_run(using_opengl_renderer): assert not config["save_last_frame"] -def test_dry_run_with_png_format(using_opengl_renderer): +def test_dry_run_with_png_format(config, using_opengl_renderer, dry_run): """Test that there are no exceptions when running a png without output""" - with tempconfig( - {"dry_run": True, "write_to_movie": False, "disable_caching": True} - ): - assert config["dry_run"] is True - scene = MyScene() - scene.render() + config.disable_caching = True + assert config["dry_run"] is True + scene = MyScene() + scene.render() -def test_dry_run_with_png_format_skipped_animations(using_opengl_renderer): +def test_dry_run_with_png_format_skipped_animations( + config, using_opengl_renderer, dry_run +): """Test that there are no exceptions when running a png without output and skipped animations""" - with tempconfig( - {"dry_run": True, "write_to_movie": False, "disable_caching": True} - ): - assert config["dry_run"] is True - scene = MyScene(skip_animations=True) - scene.render() + config.write_to_movie = False + config.disable_caching = True + assert config["dry_run"] is True + scene = MyScene(skip_animations=True) + scene.render() diff --git a/tests/opengl/test_copy_opengl.py b/tests/opengl/test_copy_opengl.py index db2e06dba4..504b7f26a5 100644 --- a/tests/opengl/test_copy_opengl.py +++ b/tests/opengl/test_copy_opengl.py @@ -2,7 +2,7 @@ from pathlib import Path -from manim import BraceLabel, config +from manim import BraceLabel from manim.mobject.opengl.opengl_mobject import OpenGLMobject @@ -19,7 +19,7 @@ def test_opengl_mobject_copy(using_opengl_renderer): assert orig.submobjects[i] is not copy.submobjects[i] -def test_bracelabel_copy(using_opengl_renderer, tmp_path): +def test_bracelabel_copy(config, using_opengl_renderer, tmp_path): """Test that a copy is a deepcopy.""" # For this test to work, we need to tweak some folders temporarily original_text_dir = config["text_dir"] diff --git a/tests/opengl/test_ipython_magic_opengl.py b/tests/opengl/test_ipython_magic_opengl.py index ad1c61a6b5..2d4617af0f 100644 --- a/tests/opengl/test_ipython_magic_opengl.py +++ b/tests/opengl/test_ipython_magic_opengl.py @@ -2,36 +2,29 @@ import re -from manim import config, tempconfig from manim.utils.ipython_magic import _generate_file_name -def test_jupyter_file_naming(): +def test_jupyter_file_naming(config, using_opengl_renderer): """Check the format of file names for jupyter""" scene_name = "SimpleScene" expected_pattern = r"[0-9a-zA-Z_]+[@_-]\d\d\d\d-\d\d-\d\d[@_-]\d\d-\d\d-\d\d" - current_renderer = config.renderer - with tempconfig({"scene_names": [scene_name], "renderer": "opengl"}): - file_name = _generate_file_name() - match = re.match(expected_pattern, file_name) - assert scene_name in file_name, ( - "Expected file to contain " + scene_name + " but got " + file_name - ) - assert match, "file name does not match expected pattern " + expected_pattern - # needs manually set back to avoid issues across tests - config.renderer = current_renderer + config.scene_names = [scene_name] + file_name = _generate_file_name() + match = re.match(expected_pattern, file_name) + assert scene_name in file_name, ( + "Expected file to contain " + scene_name + " but got " + file_name + ) + assert match, "file name does not match expected pattern " + expected_pattern -def test_jupyter_file_output(tmp_path): +def test_jupyter_file_output(tmp_path, config, using_opengl_renderer): """Check the jupyter file naming is valid and can be created""" scene_name = "SimpleScene" - current_renderer = config.renderer - with tempconfig({"scene_names": [scene_name], "renderer": "opengl"}): - file_name = _generate_file_name() - actual_path = tmp_path.with_name(file_name) - with actual_path.open("w") as outfile: - outfile.write("") - assert actual_path.exists() - assert actual_path.is_file() - # needs manually set back to avoid issues across tests - config.renderer = current_renderer + config.scene_names = [scene_name] + file_name = _generate_file_name() + actual_path = tmp_path.with_name(file_name) + with actual_path.open("w") as outfile: + outfile.write("") + assert actual_path.exists() + assert actual_path.is_file() diff --git a/tests/opengl/test_texmobject_opengl.py b/tests/opengl/test_texmobject_opengl.py index 4fe5a76f81..a9dd20ba02 100644 --- a/tests/opengl/test_texmobject_opengl.py +++ b/tests/opengl/test_texmobject_opengl.py @@ -4,15 +4,15 @@ import pytest -from manim import MathTex, SingleStringMathTex, Tex, config +from manim import MathTex, SingleStringMathTex, Tex -def test_MathTex(using_opengl_renderer): +def test_MathTex(config, using_opengl_renderer): MathTex("a^2 + b^2 = c^2") assert Path(config.media_dir, "Tex", "e4be163a00cf424f.svg").exists() -def test_SingleStringMathTex(using_opengl_renderer): +def test_SingleStringMathTex(config, using_opengl_renderer): SingleStringMathTex("test") assert Path(config.media_dir, "Tex", "8ce17c7f5013209f.svg").exists() @@ -26,7 +26,7 @@ def test_double_braces_testing(using_opengl_renderer, text_input, length_sub): assert len(t1.submobjects) == length_sub -def test_tex(using_opengl_renderer): +def test_tex(config, using_opengl_renderer): Tex("The horse does not eat cucumber salad.") assert Path(config.media_dir, "Tex", "c3945e23e546c95a.svg").exists() diff --git a/tests/test_config.py b/tests/test_config.py index 0c60d59b10..18f7691cfc 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -5,12 +5,12 @@ import numpy as np -from manim import WHITE, Scene, Square, Tex, Text, config, tempconfig +from manim import WHITE, Scene, Square, Tex, Text, tempconfig from manim._config.utils import ManimConfig from tests.assert_utils import assert_dir_exists, assert_dir_filled, assert_file_exists -def test_tempconfig(): +def test_tempconfig(config): """Test the tempconfig context manager.""" original = config.copy() @@ -41,144 +41,141 @@ def construct(self): self.wait(1) -def test_transparent(): +def test_transparent(config): """Test the 'transparent' config option.""" - orig_verbosity = config["verbosity"] - config["verbosity"] = "ERROR" - with tempconfig({"dry_run": True}): - scene = MyScene() - scene.render() - frame = scene.renderer.get_frame() + config.verbosity = "ERROR" + config.dry_run = True + + scene = MyScene() + scene.render() + frame = scene.renderer.get_frame() np.testing.assert_allclose(frame[0, 0], [0, 0, 0, 255]) - with tempconfig({"transparent": True, "dry_run": True}): - scene = MyScene() - scene.render() - frame = scene.renderer.get_frame() - np.testing.assert_allclose(frame[0, 0], [0, 0, 0, 0]) + config.transparent = True - config["verbosity"] = orig_verbosity + scene = MyScene() + scene.render() + frame = scene.renderer.get_frame() + np.testing.assert_allclose(frame[0, 0], [0, 0, 0, 0]) -def test_background_color(): +def test_background_color(config): """Test the 'background_color' config option.""" - with tempconfig({"background_color": WHITE, "verbosity": "ERROR", "dry_run": True}): - scene = MyScene() - scene.render() - frame = scene.renderer.get_frame() - np.testing.assert_allclose(frame[0, 0], [255, 255, 255, 255]) + config.background_color = WHITE + config.verbosity = "ERROR" + config.dry_run = True + + scene = MyScene() + scene.render() + frame = scene.renderer.get_frame() + np.testing.assert_allclose(frame[0, 0], [255, 255, 255, 255]) -def test_digest_file(tmp_path): + +def test_digest_file(tmp_path, config): """Test that a config file can be digested programmatically.""" - with tempconfig({}): - tmp_cfg = tempfile.NamedTemporaryFile("w", dir=tmp_path, delete=False) - tmp_cfg.write( - """ - [CLI] - media_dir = this_is_my_favorite_path - video_dir = {media_dir}/videos - sections_dir = {media_dir}/{scene_name}/prepare_for_unforeseen_consequences - frame_height = 10 - """, - ) - tmp_cfg.close() - config.digest_file(tmp_cfg.name) - - assert config.get_dir("media_dir") == Path("this_is_my_favorite_path") - assert config.get_dir("video_dir") == Path("this_is_my_favorite_path/videos") - assert config.get_dir("sections_dir", scene_name="test") == Path( - "this_is_my_favorite_path/test/prepare_for_unforeseen_consequences" - ) - - -def test_custom_dirs(tmp_path): - with tempconfig( - { - "media_dir": tmp_path, - "save_sections": True, - "log_to_file": True, - "frame_rate": 15, - "pixel_height": 854, - "pixel_width": 480, - "sections_dir": "{media_dir}/test_sections", - "video_dir": "{media_dir}/test_video", - "partial_movie_dir": "{media_dir}/test_partial_movie_dir", - "images_dir": "{media_dir}/test_images", - "text_dir": "{media_dir}/test_text", - "tex_dir": "{media_dir}/test_tex", - "log_dir": "{media_dir}/test_log", - } - ): - scene = MyScene() - scene.render() - tmp_path = Path(tmp_path) - assert_dir_filled(tmp_path / "test_sections") - assert_file_exists(tmp_path / "test_sections/MyScene.json") - - assert_dir_filled(tmp_path / "test_video") - assert_file_exists(tmp_path / "test_video/MyScene.mp4") - - assert_dir_filled(tmp_path / "test_partial_movie_dir") - assert_file_exists( - tmp_path / "test_partial_movie_dir/partial_movie_file_list.txt" - ) - - # TODO: another example with image output would be nice - assert_dir_exists(tmp_path / "test_images") - - assert_dir_filled(tmp_path / "test_text") - assert_dir_filled(tmp_path / "test_tex") - assert_dir_filled(tmp_path / "test_log") - - -def test_frame_size(tmp_path): + tmp_cfg = tempfile.NamedTemporaryFile("w", dir=tmp_path, delete=False) + tmp_cfg.write( + """ + [CLI] + media_dir = this_is_my_favorite_path + video_dir = {media_dir}/videos + sections_dir = {media_dir}/{scene_name}/prepare_for_unforeseen_consequences + frame_height = 10 + """, + ) + tmp_cfg.close() + config.digest_file(tmp_cfg.name) + + assert config.get_dir("media_dir") == Path("this_is_my_favorite_path") + assert config.get_dir("video_dir") == Path("this_is_my_favorite_path/videos") + assert config.get_dir("sections_dir", scene_name="test") == Path( + "this_is_my_favorite_path/test/prepare_for_unforeseen_consequences" + ) + + +def test_custom_dirs(tmp_path, config): + config.media_dir = tmp_path + config.save_sections = True + config.log_to_file = True + config.frame_rate = 15 + config.pixel_height = 854 + config.pixel_width = 480 + config.sections_dir = "{media_dir}/test_sections" + config.video_dir = "{media_dir}/test_video" + config.partial_movie_dir = "{media_dir}/test_partial_movie_dir" + config.images_dir = "{media_dir}/test_images" + config.text_dir = "{media_dir}/test_text" + config.tex_dir = "{media_dir}/test_tex" + config.log_dir = "{media_dir}/test_log" + + scene = MyScene() + scene.render() + tmp_path = Path(tmp_path) + assert_dir_filled(tmp_path / "test_sections") + assert_file_exists(tmp_path / "test_sections/MyScene.json") + + assert_dir_filled(tmp_path / "test_video") + assert_file_exists(tmp_path / "test_video/MyScene.mp4") + + assert_dir_filled(tmp_path / "test_partial_movie_dir") + assert_file_exists(tmp_path / "test_partial_movie_dir/partial_movie_file_list.txt") + + # TODO: another example with image output would be nice + assert_dir_exists(tmp_path / "test_images") + + assert_dir_filled(tmp_path / "test_text") + assert_dir_filled(tmp_path / "test_tex") + assert_dir_filled(tmp_path / "test_log") + + +def test_pixel_dimensions(tmp_path, config): + tmp_cfg = tempfile.NamedTemporaryFile("w", dir=tmp_path, delete=False) + tmp_cfg.write( + """ + [CLI] + pixel_height = 10 + pixel_width = 10 + """, + ) + tmp_cfg.close() + config.digest_file(tmp_cfg.name) + + # aspect ratio is set using pixel measurements + np.testing.assert_allclose(config.aspect_ratio, 1.0) + # if not specified in the cfg file, frame_width is set using the aspect ratio + np.testing.assert_allclose(config.frame_height, 8.0) + np.testing.assert_allclose(config.frame_width, 8.0) + + +def test_frame_size(tmp_path, config): """Test that the frame size can be set via config file.""" np.testing.assert_allclose( config.aspect_ratio, config.pixel_width / config.pixel_height ) np.testing.assert_allclose(config.frame_height, 8.0) - with tempconfig({}): - tmp_cfg = tempfile.NamedTemporaryFile("w", dir=tmp_path, delete=False) - tmp_cfg.write( - """ - [CLI] - pixel_height = 10 - pixel_width = 10 - """, - ) - tmp_cfg.close() - config.digest_file(tmp_cfg.name) - - # aspect ratio is set using pixel measurements - np.testing.assert_allclose(config.aspect_ratio, 1.0) - # if not specified in the cfg file, frame_width is set using the aspect ratio - np.testing.assert_allclose(config.frame_height, 8.0) - np.testing.assert_allclose(config.frame_width, 8.0) - - with tempconfig({}): - tmp_cfg = tempfile.NamedTemporaryFile("w", dir=tmp_path, delete=False) - tmp_cfg.write( - """ - [CLI] - pixel_height = 10 - pixel_width = 10 - frame_height = 10 - frame_width = 10 - """, - ) - tmp_cfg.close() - config.digest_file(tmp_cfg.name) - - np.testing.assert_allclose(config.aspect_ratio, 1.0) - # if both are specified in the cfg file, the aspect ratio is ignored - np.testing.assert_allclose(config.frame_height, 10.0) - np.testing.assert_allclose(config.frame_width, 10.0) - - -def test_temporary_dry_run(): + tmp_cfg = tempfile.NamedTemporaryFile("w", dir=tmp_path, delete=False) + tmp_cfg.write( + """ + [CLI] + pixel_height = 10 + pixel_width = 10 + frame_height = 10 + frame_width = 10 + """, + ) + tmp_cfg.close() + config.digest_file(tmp_cfg.name) + + np.testing.assert_allclose(config.aspect_ratio, 1.0) + # if both are specified in the cfg file, the aspect ratio is ignored + np.testing.assert_allclose(config.frame_height, 10.0) + np.testing.assert_allclose(config.frame_width, 10.0) + + +def test_temporary_dry_run(config): """Test that tempconfig correctly restores after setting dry_run.""" assert config["write_to_movie"] assert not config["save_last_frame"] @@ -191,24 +188,23 @@ def test_temporary_dry_run(): assert not config["save_last_frame"] -def test_dry_run_with_png_format(): +def test_dry_run_with_png_format(config, dry_run): """Test that there are no exceptions when running a png without output""" - with tempconfig( - {"dry_run": True, "write_to_movie": False, "disable_caching": True} - ): - assert config["dry_run"] is True - scene = MyScene() - scene.render() + + config.write_to_movie = False + config.disable_caching = True + assert config.dry_run is True + scene = MyScene() + scene.render() -def test_dry_run_with_png_format_skipped_animations(): +def test_dry_run_with_png_format_skipped_animations(config, dry_run): """Test that there are no exceptions when running a png without output and skipped animations""" - with tempconfig( - {"dry_run": True, "write_to_movie": False, "disable_caching": True} - ): - assert config["dry_run"] is True - scene = MyScene(skip_animations=True) - scene.render() + config.write_to_movie = False + config.disable_caching = True + assert config["dry_run"] is True + scene = MyScene(skip_animations=True) + scene.render() def test_tex_template_file(tmp_path): diff --git a/tests/test_ipython_magic.py b/tests/test_ipython_magic.py index 91d1fba8c2..6452d58de5 100644 --- a/tests/test_ipython_magic.py +++ b/tests/test_ipython_magic.py @@ -2,30 +2,29 @@ import re -from manim import tempconfig from manim.utils.ipython_magic import _generate_file_name -def test_jupyter_file_naming(): +def test_jupyter_file_naming(config): """Check the format of file names for jupyter""" scene_name = "SimpleScene" expected_pattern = r"[0-9a-zA-Z_]+[@_-]\d\d\d\d-\d\d-\d\d[@_-]\d\d-\d\d-\d\d" - with tempconfig({"scene_names": [scene_name]}): - file_name = _generate_file_name() - match = re.match(expected_pattern, file_name) - assert scene_name in file_name, ( - "Expected file to contain " + scene_name + " but got " + file_name - ) - assert match, "file name does not match expected pattern " + expected_pattern + config.scene_names = [scene_name] + file_name = _generate_file_name() + match = re.match(expected_pattern, file_name) + assert scene_name in file_name, ( + "Expected file to contain " + scene_name + " but got " + file_name + ) + assert match, "file name does not match expected pattern " + expected_pattern -def test_jupyter_file_output(tmp_path): +def test_jupyter_file_output(tmp_path, config): """Check the jupyter file naming is valid and can be created""" scene_name = "SimpleScene" - with tempconfig({"scene_names": [scene_name]}): - file_name = _generate_file_name() - actual_path = tmp_path.with_name(file_name) - with actual_path.open("w") as outfile: - outfile.write("") - assert actual_path.exists() - assert actual_path.is_file() + config.scene_names = [scene_name] + file_name = _generate_file_name() + actual_path = tmp_path.with_name(file_name) + with actual_path.open("w") as outfile: + outfile.write("") + assert actual_path.exists() + assert actual_path.is_file() diff --git a/tests/test_scene_rendering/opengl/test_opengl_renderer.py b/tests/test_scene_rendering/opengl/test_opengl_renderer.py index 95f7adde0b..71454d225f 100644 --- a/tests/test_scene_rendering/opengl/test_opengl_renderer.py +++ b/tests/test_scene_rendering/opengl/test_opengl_renderer.py @@ -3,6 +3,7 @@ import platform from unittest.mock import Mock +import numpy as np import pytest from manim.renderer.opengl_renderer import OpenGLRenderer @@ -10,18 +11,21 @@ from tests.test_scene_rendering.simple_scenes import * -def test_write_to_movie_disables_window(using_temp_opengl_config, disabling_caching): +def test_write_to_movie_disables_window( + config, using_temp_opengl_config, disabling_caching +): """write_to_movie should disable window by default""" scene = SquareToCircle() renderer = scene.renderer renderer.update_frame = Mock(wraps=renderer.update_frame) scene.render() assert renderer.window is None - assert_file_exists(config["output_file"]) + assert_file_exists(config.output_file) @pytest.mark.skip(reason="Temporarily skip due to failing in Windows CI") # type: ignore def test_force_window_opengl_render_with_movies( + config, using_temp_opengl_config, force_window_config_write_to_movie, disabling_caching, @@ -53,9 +57,10 @@ def test_force_window_opengl_render_with_format( renderer.window.close() -@pytest.mark.parametrize("enable_preview", [False]) -def test_get_frame_with_preview_disabled(use_opengl_renderer): +def test_get_frame_with_preview_disabled(config, using_opengl_renderer): """Get frame is able to fetch frame with the correct dimensions when preview is disabled""" + config.preview = False + scene = SquareToCircle() assert isinstance(scene.renderer, OpenGLRenderer) assert not config.preview @@ -70,9 +75,10 @@ def test_get_frame_with_preview_disabled(use_opengl_renderer): @pytest.mark.slow -@pytest.mark.parametrize("enable_preview", [True]) -def test_get_frame_with_preview_enabled(use_opengl_renderer): +def test_get_frame_with_preview_enabled(config, using_opengl_renderer): """Get frame is able to fetch frame with the correct dimensions when preview is enabled""" + config.preview = True + scene = SquareToCircle() assert isinstance(scene.renderer, OpenGLRenderer) assert config.preview is True @@ -86,8 +92,9 @@ def test_get_frame_with_preview_enabled(use_opengl_renderer): assert renderer.get_pixel_shape()[1] == frame.shape[0] -@pytest.mark.parametrize("enable_preview", [True]) -def test_pixel_coords_to_space_coords(use_opengl_renderer): +def test_pixel_coords_to_space_coords(config, using_opengl_renderer): + config.preview = True + scene = SquareToCircle() assert isinstance(scene.renderer, OpenGLRenderer) diff --git a/tests/test_scene_rendering/opengl/test_play_logic_opengl.py b/tests/test_scene_rendering/opengl/test_play_logic_opengl.py index cb640c5f80..64c4c39204 100644 --- a/tests/test_scene_rendering/opengl/test_play_logic_opengl.py +++ b/tests/test_scene_rendering/opengl/test_play_logic_opengl.py @@ -5,8 +5,11 @@ import pytest -from manim import * -from manim import config +from manim import ( + Scene, + ValueTracker, + np, +) from ..simple_scenes import ( SceneForFrozenFrameTests, @@ -23,7 +26,7 @@ reason="Mock object has a different implementation in python 3.7, which makes it broken with this logic.", ) @pytest.mark.parametrize("frame_rate", argvalues=[15, 30, 60]) -def test_t_values(using_temp_opengl_config, disabling_caching, frame_rate): +def test_t_values(config, using_temp_opengl_config, disabling_caching, frame_rate): """Test that the framerate corresponds to the number of t values generated""" config.frame_rate = frame_rate scene = SquareToCircle() @@ -36,10 +39,6 @@ def test_t_values(using_temp_opengl_config, disabling_caching, frame_rate): ) -@pytest.mark.skipif( - sys.version_info < (3, 8), - reason="Mock object has a different implementation in python 3.7, which makes it broken with this logic.", -) def test_t_values_with_skip_animations(using_temp_opengl_config, disabling_caching): """Test the behaviour of scene.skip_animations""" scene = SquareToCircle() @@ -95,7 +94,7 @@ def test_t_values_with_cached_data(using_temp_opengl_config): @pytest.mark.xfail(reason="Not currently handled correctly for opengl") -def test_t_values_save_last_frame(using_temp_opengl_config): +def test_t_values_save_last_frame(config, using_temp_opengl_config): """Test that there is only one t value handled when only saving the last frame""" config.save_last_frame = True scene = SquareToCircle() diff --git a/tests/test_scene_rendering/simple_scenes.py b/tests/test_scene_rendering/simple_scenes.py index 8f4dd9d434..922a93ee6c 100644 --- a/tests/test_scene_rendering/simple_scenes.py +++ b/tests/test_scene_rendering/simple_scenes.py @@ -4,6 +4,21 @@ from manim import * +__all__ = [ + "SquareToCircle", + "SceneWithMultipleCalls", + "SceneWithMultipleWaitCalls", + "NoAnimations", + "SceneWithStaticWait", + "SceneWithSceneUpdater", + "SceneForFrozenFrameTests", + "SceneWithNonStaticWait", + "StaticScene", + "InteractiveStaticScene", + "SceneWithSections", + "ElaborateSceneWithSections", +] + class SquareToCircle(Scene): def construct(self): diff --git a/tests/test_scene_rendering/test_play_logic.py b/tests/test_scene_rendering/test_play_logic.py index a0d97920bd..d62a5cf051 100644 --- a/tests/test_scene_rendering/test_play_logic.py +++ b/tests/test_scene_rendering/test_play_logic.py @@ -5,8 +5,14 @@ import pytest -from manim import * -from manim import config +from manim import ( + Dot, + Mobject, + Scene, + ValueTracker, + Wait, + np, +) from .simple_scenes import ( SceneForFrozenFrameTests, @@ -18,12 +24,8 @@ ) -@pytest.mark.skipif( - sys.version_info < (3, 8), - reason="Mock object has a different implementation in python 3.7, which makes it broken with this logic.", -) @pytest.mark.parametrize("frame_rate", argvalues=[15, 30, 60]) -def test_t_values(using_temp_config, disabling_caching, frame_rate): +def test_t_values(config, using_temp_config, disabling_caching, frame_rate): """Test that the framerate corresponds to the number of t values generated""" config.frame_rate = frame_rate scene = SquareToCircle() @@ -110,7 +112,7 @@ def test_t_values_with_cached_data(using_temp_config): assert scene.update_to_time.call_count == 10 -def test_t_values_save_last_frame(using_temp_config): +def test_t_values_save_last_frame(config, using_temp_config): """Test that there is only one t value handled when only saving the last frame""" config.save_last_frame = True scene = SquareToCircle()