code: def test_groupby_agg():
      df = pd.DataFrame(
          {
              "a": np.random.choice([2, 3, 4], size=(20,)),
              "b": np.random.choice([2, 3, 4], size=(20,)),
          }
      )
      mdf = md.DataFrame(df, chunk_size=3)
      r = mdf.groupby("a").agg("sum", method="tree")
      assert isinstance(r.op, DataFrameGroupByAgg)
      assert isinstance(r, DataFrame)
      assert r.op.method == "tree"
      r = tile(r)
      assert len(r.chunks) == 1
      assert r.chunks[0].op.stage == OperandStage.agg
      assert len(r.chunks[0].inputs) == 1
      assert len(r.chunks[0].inputs[0].inputs) == 2
  
      df = pd.DataFrame(
          {
              "c1": range(10),
              "c2": np.random.choice(["a", "b", "c"], (10,)),
              "c3": np.random.rand(10),
          }
      )
      mdf = md.DataFrame(df, chunk_size=2)
      r = mdf.groupby("c2", sort=False).sum(method="shuffle")
  
      assert isinstance(r.op, DataFrameGroupByAgg)
      assert isinstance(r, DataFrame)
  
      r = tile(r)
      assert len(r.chunks) == 5
      for chunk in r.chunks:
          assert isinstance(chunk.op, DataFrameGroupByAgg)
          assert chunk.op.stage == OperandStage.agg
          assert isinstance(chunk.inputs[0].op, DataFrameGroupByOperand)
          assert chunk.inputs[0].op.stage == OperandStage.reduce
          assert isinstance(
              chunk.inputs[0].inputs[0].op, DataFrameShuffleProxy
          )
          assert isinstance(
              chunk.inputs[0].inputs[0].inputs[0].op,
              DataFrameGroupByOperand,
          )
          assert (
              chunk.inputs[0].inputs[0].inputs[0].op.stage
              == OperandStage.map
          )
  
          agg_chunk = chunk.inputs[0].inputs[0].inputs[0].inputs[0]
          assert agg_chunk.op.stage == OperandStage.map
  
      r = mdf.groupby(
          "c2",
      ).sum(method="shuffle")
  
      assert isinstance(r.op, DataFrameGroupByAgg)
      assert isinstance(r, DataFrame)
  
      r = tile(r)
      assert len(r.chunks) == 5
      for chunk in r.chunks:
          assert isinstance(chunk.op, DataFrameGroupByAgg)
          assert chunk.op.stage == OperandStage.agg
          assert isinstance(
              chunk.inputs[0].op, DataFrameGroupbySortShuffle
          )
          assert chunk.inputs[0].op.stage == OperandStage.reduce
          assert isinstance(
              chunk.inputs[0].inputs[0].op, DataFrameShuffleProxy
          )
          assert isinstance(
              chunk.inputs[0].inputs[0].inputs[0].op,
              DataFrameGroupbySortShuffle,
          )
          assert (
              chunk.inputs[0].inputs[0].inputs[0].op.stage
              == OperandStage.map
          )
  
          agg_chunk = chunk.inputs[0].inputs[0].inputs[0].inputs[0]
          assert agg_chunk.op.stage == OperandStage.map
  
      # test unknown method
      with pytest.raises(ValueError):
          mdf.groupby("c2").sum(method="not_exist")
  
imports: from collections import OrderedDict
  import numpy
  import pandas
  import pytest
  from ..sort import DataFrameGroupbySortShuffle
  from ....None import dataframe
  from ....None import opcodes
  from ....config import option_context
  from ....core import OutputType, tile
  from ....core.operand import OperandStage
  from ...core import DataFrameGroupBy, SeriesGroupBy, DataFrame
  from ..core import DataFrameGroupByOperand, DataFrameShuffleProxy
  from ..aggregation import DataFrameGroupByAgg
  from ..getitem import GroupByIndex
label_desc: Use image node_id 3 for calling a global function with example usage: test_groupby_agg() without return types