code: def test_plot_forecast_vs_actual():
      """Tests plot_forecast_vs_actual function"""
      size = 200
      df = pd.DataFrame(
          {
              cst.TIME_COL: pd.date_range(
                  start="2018-01-01", periods=size, freq="H"
              ),
              cst.ACTUAL_COL: np.random.normal(scale=10, size=size),
          }
      )
      df[cst.PREDICTED_COL] = df[cst.ACTUAL_COL] + np.random.normal(
          size=size
      )
      df[cst.PREDICTED_LOWER_COL] = df[cst.PREDICTED_COL] - 10
      df[cst.PREDICTED_UPPER_COL] = df[cst.PREDICTED_COL] + 10
      fig = plot_forecast_vs_actual(df)
      assert len(fig.data) == 4
      assert fig.layout.title.text == "Forecast vs Actual"
      assert fig.layout.xaxis.title.text == cst.TIME_COL
      assert fig.layout.yaxis.title.text == cst.VALUE_COL
  
      # checks if figure can be manipulated
      update_layout = dict(
          yaxis=dict(title="new ylabel"),
          title_text="new title",
          title_x=0.5,
          title_font_size=30,
      )
      fig.update_layout(update_layout)
      assert (
          len(fig.to_html(include_plotlyjs=False, full_html=True)) > 0
      )
  
      # checks if lower and upper bound are optional
      fig = plot_forecast_vs_actual(df, predicted_lower_col=None)
      assert len(fig.data) == 3
      fig = plot_forecast_vs_actual(df, predicted_upper_col=None)
      assert len(fig.data) == 3
      fig = plot_forecast_vs_actual(
          df,
          predicted_lower_col=None,
          predicted_upper_col=None,
          title="new title",
      )
      assert len(fig.data) == 2
      assert fig.layout.title.text == "new title"
  
      # checks if train end date can be plotted
      fig = plot_forecast_vs_actual(
          df,
          train_end_date=df[cst.TIME_COL][150],
          actual_mode="markers",
      )
      assert len(fig.layout.annotations) > 0
  
      # sets a bunch of options
      fig = plot_forecast_vs_actual(
          df,
          train_end_date=df[cst.TIME_COL][150],
          showlegend=False,
          actual_mode="lines",
          actual_points_color="blue",
          actual_points_size=1.0,
          actual_color_opacity=0.3,
          forecast_curve_color="red",
          forecast_curve_dash="solid",
          ci_band_color="green",
          ci_boundary_curve_color="orange",
          ci_boundary_curve_width=2.0,
          vertical_line_color="black",
          vertical_line_width=5.0,
      )
      assert len(fig.data) == 4
      assert not fig.layout.showlegend
  
imports: import datetime
  from datetime import datetime
  from functools import partial
  import numpy
  import pandas
  import pytest
  from pandas.testing import assert_frame_equal
  from plotly.colors import DEFAULT_PLOTLY_COLORS
  from testfixtures import LogCapture
  import greykite.common.constants
  from greykite.common.evaluation import EvaluationMetricEnum
  from greykite.common.viz.timeseries_plotting import add_groupby_column
  from greykite.common.viz.timeseries_plotting import flexible_grouping_evaluation
  from greykite.common.viz.timeseries_plotting import grouping_evaluation
  from greykite.common.viz.timeseries_plotting import plot_dual_axis_figure
  from greykite.common.viz.timeseries_plotting import plot_forecast_vs_actual
  from greykite.common.viz.timeseries_plotting import plot_multivariate
  from greykite.common.viz.timeseries_plotting import plot_multivariate_grouped
  from greykite.common.viz.timeseries_plotting import plot_univariate
  from greykite.common.viz.timeseries_plotting import split_range_into_groups
label_desc: Use image node_id 4 for calling a global function with example usage: test_plot_forecast_vs_actual() without return types