code: def test_append_tags(self):
      # given
      backend = mock.MagicMock()
      experiment = Experiment(
          backend, a_project(), an_experiment_id(), a_uuid_string()
      )
  
      # and
      def build_call(tags_list):
          return call(
              experiment=experiment,
              tags_to_add=tags_list,
              tags_to_delete=[],
          )
  
      # when
      experiment.append_tag("tag")
      experiment.append_tag(["tag1", "tag2", "tag3"])
      experiment.append_tag("tag1", "tag2", "tag3")
      experiment.append_tags("tag")
      experiment.append_tags(["tag1", "tag2", "tag3"])
      experiment.append_tags("tag1", "tag2", "tag3")
  
      # then
      backend.update_tags.assert_has_calls(
          [
              build_call(["tag"]),
              build_call(["tag1", "tag2", "tag3"]),
              build_call(["tag1", "tag2", "tag3"]),
              build_call(["tag"]),
              build_call(["tag1", "tag2", "tag3"]),
              build_call(["tag1", "tag2", "tag3"]),
          ]
      )
  
imports: import base64
  import random
  import time
  import unittest
  from io import StringIO
  import mock
  import pandas
  from mock import MagicMock, call
  from munch import Munch
  from pandas.testing import assert_frame_equal
  from neptune.legacy.experiments import Experiment
  from neptune.legacy.internal.channels.channels import ChannelType, ChannelValue
  from tests.unit.neptune.legacy.random_utils import a_project, a_string, a_uuid_string, an_experiment_id, sort_df_by_columns
label_desc: Use image node_id 4 for calling the TestExperiment obj's underlying member method code with example usage: obj.test_append_tags() and returns: call