Back to Repositories

Testing Plot Component Visualization Processing in gradio-app/gradio

A comprehensive test suite for the Plot component in Gradio, focusing on matplotlib and altair integration. The tests verify plot rendering, format handling, and interface integration for both static and dynamic visualization scenarios.

Test Coverage Overview

The test suite provides thorough coverage of the Plot component’s core functionality:
  • Interface integration testing with matplotlib plots
  • Static plot rendering verification
  • Altair chart processing and conversion
  • Plot format parameter handling
Tests cover both synchronous and asynchronous implementations, ensuring robust visualization processing.

Implementation Analysis

The testing approach utilizes pytest’s async capabilities and context managers for matplotlib backend handling. Key patterns include:
  • Async testing with @pytest.mark.asyncio for interface processing
  • MatplotlibBackendMananger context for proper plot handling
  • Integration testing with both matplotlib and altair visualization libraries

Technical Details

Testing infrastructure includes:
  • pytest as the primary testing framework
  • matplotlib for basic plotting functionality
  • altair and vega_datasets for alternative visualization testing
  • Custom utility classes (MatplotlibBackendMananger) for backend management

Best Practices Demonstrated

The test suite exemplifies several testing best practices:
  • Isolated test cases with clear single-responsibility focus
  • Proper resource management with context managers
  • Comprehensive assertion checks for both data types and content
  • Multiple visualization library support testing

gradio-app/gradio

test/components/test_plot.py

            
import pytest

import gradio as gr
from gradio import utils


class TestPlot:
    @pytest.mark.asyncio
    async def test_in_interface_as_output(self):
        """
        Interface, process
        """

        def plot(num):
            import matplotlib.pyplot as plt

            fig = plt.figure()
            plt.plot(range(num), range(num))
            return fig

        iface = gr.Interface(plot, "slider", "plot")
        with utils.MatplotlibBackendMananger():
            output = await iface.process_api(block_fn=0, inputs=[10])
        assert output["data"][0]["type"] == "matplotlib"
        assert output["data"][0]["plot"].startswith("data:image/webp;base64")

    def test_static(self):
        """
        postprocess
        """
        with utils.MatplotlibBackendMananger():
            import matplotlib.pyplot as plt

            fig = plt.figure()
            plt.plot([1, 2, 3], [1, 2, 3])

        component = gr.Plot(fig)
        assert component.get_config().get("value") is not None
        component = gr.Plot(None)
        assert component.get_config().get("value") is None

    def test_postprocess_altair(self):
        import altair as alt
        from vega_datasets import data

        cars = data.cars()
        chart = (
            alt.Chart(cars)
            .mark_point()
            .encode(
                x="Horsepower",
                y="Miles_per_Gallon",
                color="Origin",
            )
        )
        assert (out := gr.Plot().postprocess(chart))
        out = out.model_dump()
        assert isinstance(out["plot"], str)
        assert out["plot"] == chart.to_json()

    def test_plot_format_parameter(self):
        """
        postprocess
        """
        with utils.MatplotlibBackendMananger():
            import matplotlib.pyplot as plt

            fig = plt.figure()
            plt.plot([1, 2, 3], [1, 2, 3])

        component = gr.Plot(format="jpeg")
        assert (result := component.postprocess(fig))
        assert result.plot.startswith("data:image/jpeg")