Skip to content

Commit

Permalink
Add ugly tests
Browse files Browse the repository at this point in the history
  • Loading branch information
antonymilne committed Aug 6, 2024
1 parent 14fb4d4 commit 51ccb77
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 10 deletions.
5 changes: 3 additions & 2 deletions vizro-core/src/vizro/_vizro.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,9 @@ def build(self, dashboard: Dashboard):
# everything else gets overridden in the post-fig creation layout.template update in Graph.__call__ and the
# clientside theme selector callback.
# Note this setting of global template isn't undone anywhere. If we really wanted to then we could try and
# put in some teardown code, but it would probably never be 100% reliable. Remember this template setting
# can't go in run() though since it's needed even in deployment.
# put in some teardown code, but it would probably never be 100% reliable. Vizro._reset can't do this well
# either because it's a staticmethod. Remember this template setting can't go in run() though since it's needed
# even in deployment.
pio.templates.default = dashboard.theme

# Note that model instantiation and pre_build are independent of Dash.
Expand Down
8 changes: 4 additions & 4 deletions vizro-core/src/vizro/models/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,8 +252,8 @@ def _check_type(cls, captured_callable: CapturedCallable, field: ModelField) ->


@contextmanager
def _pio_templates_default(default: Literal["vizro_light", "vizro_dark"]):
"""Sets pio.templates.default and then reverts it.
def _pio_templates_default():
"""Sets pio.templates.default to "vizro_dark" and then reverts it.
This is to ensure that in a Jupyter notebook captured charts look the same as when they're in the dashboard. When
the context manager exits the global theme is reverted just to keep things clean (e.g. if you really wanted to,
Expand All @@ -270,7 +270,7 @@ def _pio_templates_default(default: Literal["vizro_light", "vizro_dark"]):
# If the user has set pio.templates.default to a vizro theme already, no need to change it.
if old_default not in ["vizro_dark", "vizro_light"]:
template_changed = True
pio.templates.default = default
pio.templates.default = "vizro_dark"

# Revert the template. This is done in a try/finally so that if the code wrapped inside the context manager (i.e.
# plotting functions) raises an exception, pio.templates.default is still reverted. This is not very important
Expand Down Expand Up @@ -374,7 +374,7 @@ def wrapped(*args, **kwargs) -> _DashboardReadyFigure:
# We don't want to update the captured_callable in the same way, since it's only used inside the
# dashboard, at which point the global pio.templates.default is always set anyway according to
# the dashboard theme and then updated according to the theme selector.
with _pio_templates_default("vizro_dark") as default_template:
with _pio_templates_default() as default_template:
fig = func(*args, **kwargs)
# Update the fig.layout.template just to ensure absolute consistency with how the dashboard
# works.
Expand Down
6 changes: 6 additions & 0 deletions vizro-core/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import pytest
from vizro import Vizro
import plotly.io as pio

# Setting pio.templates.default here is a bit of a hack. This is executed on Vizro.build, but some tests
# that don't run Vizro.build still expect it to be set. Ideally these tests would set the theme themselves or not
# pay attention to the template in the test if it's not relevant.
pio.templates.default = "vizro_dark"

# Allow our custom assert functions in tests_utils/asserts.py to do introspection nicely still.
# See https://pytest.org/en/7.4.x/how-to/assert.html#assertion-introspection-details
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@ def target_scatter_filtered_continent_and_pop_parameter_y_and_x(request, gapmind
]
scatter_params["y"] = y
scatter_params["x"] = x
return px.scatter(data, template=dark if template == "vizro_dark" else light, **scatter_params).update_layout(
margin_t=24
)
return px.scatter(data, template=template, **scatter_params).update_layout(margin_t=24)


@pytest.fixture
Expand All @@ -32,7 +30,7 @@ def target_box_filtered_continent_and_pop_parameter_y_and_x(request, gapminder_2
]
box_params["y"] = y
box_params["x"] = x
return px.box(data, template=dark if template == "vizro_dark" else light, **box_params).update_layout(margin_t=24)
return px.box(data, template=template, **box_params).update_layout(margin_t=24)


@pytest.fixture
Expand Down
1 change: 1 addition & 0 deletions vizro-core/tests/unit/vizro/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from vizro import Vizro
from vizro.figures import kpi_card
from vizro.tables import dash_ag_grid, dash_data_table
import plotly.io as pio


@pytest.fixture
Expand Down
120 changes: 120 additions & 0 deletions vizro-core/tests/unit/vizro/models/test_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import plotly.graph_objects as go
import pytest

import plotly.io as pio

try:
from pydantic.v1 import Field, ValidationError
except ImportError: # pragma: no cov
Expand Down Expand Up @@ -281,3 +283,121 @@ class ModelWithInvalidModule(VizroBaseModel):
ValueError, match="_target_=decorated_graph_function cannot be imported from invalid.module."
):
ModelWithInvalidModule(function=config)


@capture("graph")
def decorated_graph_function(data_frame):
return go.Figure()


@capture("graph")
def decorated_graph_function_themed(data_frame, template):
fig = go.Figure()
fig.layout.template = template
return fig


@capture("graph")
def decorated_graph_function_crash(data_frame):
raise RuntimeError("Crash")


# @capture("graph")
# def decorated_graph_function(data_frame):
# return px.

# @pytest.fixture(params=["vizro_dark", "vizro_light", "plotly"])
# def template(request):
# return request.param


@pytest.fixture
def set_pio_default_template_dark():
old_default = pio.templates.default
pio.templates.default = "vizro_dark"
yield
pio.templates.default = old_default


@pytest.fixture
def set_pio_default_template_light():
old_default = pio.templates.default
pio.templates.default = "vizro_light"
yield
pio.templates.default = old_default


@pytest.fixture
def set_pio_default_template_plotly():
old_default = pio.templates.default
pio.templates.default = "plotly"
yield
pio.templates.default = old_default


class TestGraphTemplate:
def test(self, set_pio_default_template_dark):
graph = decorated_graph_function(None)
assert graph.layout.template == pio.templates["vizro_dark"]
assert pio.templates.default == "vizro_dark"

def test2(self, set_pio_default_template_light):
graph = decorated_graph_function(None)
assert graph.layout.template == pio.templates["vizro_light"]
assert pio.templates.default == "vizro_light"

def test3(self, set_pio_default_template_plotly):
graph = decorated_graph_function(None)
assert graph.layout.template == pio.templates["vizro_dark"]
assert pio.templates.default == "plotly"

def test4(self, set_pio_default_template_dark):
graph = decorated_graph_function_themed(None, "vizro_dark")
assert graph.layout.template == pio.templates["vizro_dark"]
assert pio.templates.default == "vizro_dark"

def test5(self, set_pio_default_template_dark):
graph = decorated_graph_function_themed(None, "vizro_light")
assert graph.layout.template == pio.templates["vizro_light"]
assert pio.templates.default == "vizro_dark"

def test6(self, set_pio_default_template_dark):
graph = decorated_graph_function_themed(None, "plotly")
assert graph.layout.template == pio.templates["vizro_dark"]
assert pio.templates.default == "vizro_dark"

def test7(self, set_pio_default_template_light):
graph = decorated_graph_function_themed(None, "vizro_dark")
assert graph.layout.template == pio.templates["vizro_dark"]
assert pio.templates.default == "vizro_light"

def test8(self, set_pio_default_template_light):
graph = decorated_graph_function_themed(None, "vizro_light")
assert graph.layout.template == pio.templates["vizro_light"]
assert pio.templates.default == "vizro_light"

def test9(self, set_pio_default_template_light):
graph = decorated_graph_function_themed(None, "plotly")
assert graph.layout.template == pio.templates["vizro_light"]
assert pio.templates.default == "vizro_light"

def test10(self, set_pio_default_template_plotly):
graph = decorated_graph_function_themed(None, "vizro_dark")
assert graph.layout.template == pio.templates["vizro_dark"]
assert pio.templates.default == "plotly"

def test11(self, set_pio_default_template_plotly):
graph = decorated_graph_function_themed(None, "vizro_light")
assert graph.layout.template == pio.templates["vizro_light"]
assert pio.templates.default == "plotly"

def test12(self, set_pio_default_template_plotly):
graph = decorated_graph_function_themed(None, "plotly")
assert graph.layout.template == pio.templates["vizro_dark"]
assert pio.templates.default == "plotly"

# Could parametrise this 3 times too if can be bothered...
def test13(self, set_pio_default_template_plotly):
with pytest.raises(RuntimeError, match="Crash"):
decorated_graph_function_crash(None)
assert pio.templates.default == "plotly"

0 comments on commit 51ccb77

Please sign in to comment.