code: def test_pipeline_union(X, fs):
      """Tests PandasFeatureUnion on a pipeline of transformers and estimator, and shows
      that null model extracted from estimator in pipeline is equivalent to null model trained
      directly"""
      model_estimator = Pipeline(
          [
              ("input", fs),
              (
                  "estimator",
                  SimpleSilverkiteEstimator(
                      score_func=mean_squared_error,
                      coverage=0.80,
                      null_model_params={"strategy": "mean"},
                  ),
              ),
          ]
      )
  
      # fits pipeline with estimator, and extract dummy null model
      z_cutoff = 2.0
      model_estimator.set_params(
          input__response__outlier__z_cutoff=z_cutoff
      )
      model_estimator.fit(X)
      output_estimator_null = model_estimator.steps[-1][
          -1
      ].null_model.predict(X)
  
      # fits pipeline with dummy estimator
      model_dummy = Pipeline(
          [
              ("input", fs),
              (
                  "dummy",
                  DummyEstimator(
                      score_func=mean_squared_error, strategy="mean"
                  ),
              ),
          ]
      )
      model_dummy.fit(X)
      output_dummy = model_dummy.predict(X)
  
      # fits dummy estimator by hand, without Pipeline
      X_after_column_select = ColumnSelector([VALUE_COL]).fit_transform(
          X
      )
      X_after_z_score = ZscoreOutlierTransformer(
          z_cutoff=z_cutoff
      ).fit_transform(X_after_column_select)
      X_after_null = NullTransformer().fit_transform(X_after_z_score)
      X_after_union = pd.concat([X[TIME_COL], X_after_null], axis=1)
      model_hand = DummyEstimator(strategy="mean")
      model_hand.fit(X_after_union)
      output_by_hand = model_hand.predict(X_after_union)
  
      assert output_estimator_null.equals(output_by_hand)
      assert output_dummy.equals(output_by_hand)
  
imports: import numpy
  import pandas
  import pytest
  from sklearn.metrics import mean_squared_error
  from sklearn.pipeline import Pipeline
  from greykite.common.constants import ACTUAL_COL
  from greykite.common.constants import TIME_COL
  from greykite.common.constants import VALUE_COL
  from greykite.common.python_utils import assert_equal
  from greykite.sklearn.estimator.null_model import DummyEstimator
  from greykite.sklearn.estimator.simple_silverkite_estimator import SimpleSilverkiteEstimator
  from greykite.sklearn.transform.column_selector import ColumnSelector
  from greykite.sklearn.transform.difference_based_outlier_transformer import DifferenceBasedOutlierTransformer
  from greykite.sklearn.transform.null_transformer import NullTransformer
  from greykite.sklearn.transform.pandas_feature_union import PandasFeatureUnion
  from greykite.sklearn.transform.zscore_outlier_transformer import ZscoreOutlierTransformer
label_desc: Use image node_id 6 for calling a global function with example usage: test_pipeline_union(X, fs) without return types