class_docstr: A helper mixin for testing Reverb adders.
  
  Note that any test inheriting from this mixin must also inherit from something
  that provides the Python unittest assert methods.
docstr: Runs a unit test case for the adder.
  
  Args:
    adder: The instance of `Adder` that is being tested.
    first: The first `dm_env.TimeStep` that is used to call
      `Adder.add_first()`.
    steps: A sequence of (action, timestep) tuples that are passed to
      `Adder.add()`.
    expected_items: The sequence of items that are expected to be created
      by calling the adder's `add_first()` method on `first` and `add()` on
      all of the elements in `steps`.
    signature: Signature that written items must be compatible with.
    pack_expected_items: Deprecated and not used. If true the expected items
      are given unpacked and need to be packed in a list before comparison.
    stack_sequence_fields: Whether to stack the sequence fields of the
      expected items before comparing to the observed items. Usually False
      for transition adders and True for both episode and sequence adders.
    repeat_episode_times: How many times to run an episode.
    end_behavior: How end of episode should be handled.
    item_transform: Transformation of item simulating the work done by the
      dataset pipeline on the learner in a real setup.
docstr_tok: ["Runs","a","unit","test","case","for","the","adder",".","Args",":","adder",":","The","instance","of","`","Adder","`","that","is","being","tested",".","first",":","The","first","`","dm_env.TimeStep","`","that","is","used","to","call","`","Adder.add_first","(",")","`",".","steps",":","A","sequence","of","(","action",",","timestep",")","tuples","that","are","passed","to","`","Adder.add","(",")","`",".","expected_items",":","The","sequence","of","items","that","are","expected","to","be","created","by","calling","the","adder","'s","`","add_first","(",")","`","method","on","`","first","`","and","`","add","(",")","`","on","all","of","the","elements","in","`","steps","`",".","signature",":","Signature","that","written","items","must","be","compatible","with",".","pack_expected_items",":","Deprecated","and","not","used",".","If","true","the","expected","items","are","given","unpacked","and","need","to","be","packed","in","a","list","before","comparison",".","stack_sequence_fields",":","Whether","to","stack","the","sequence","fields","of","the","expected","items","before","comparing","to","the","observed","items",".","Usually","False","for","transition","adders","and","True","for","both","episode","and","sequence","adders",".","repeat_episode_times",":","How","many","times","to","run","an","episode",".","end_behavior",":","How","end","of","episode","should","be","handled",".","item_transform",":","Transformation","of","item","simulating","the","work","done","by","the","dataset","pipeline","on","the","learner","in","a","real","setup","."]
code: def run_test_adder(
      self,
      adder: adders_base.Adder,
      first: dm_env.TimeStep,
      steps: Sequence[Step],
      expected_items: Sequence[Any],
      signature: types.NestedSpec,
      pack_expected_items: bool = False,
      stack_sequence_fields: bool = True,
      repeat_episode_times: int = 1,
      end_behavior: adders.EndBehavior = adders.EndBehavior.ZERO_PAD,
      item_transform: Optional[
          Callable[[Sequence[np.ndarray]], Any]
      ] = None,
  ):
      """Runs a unit test case for the adder.
  
      Args:
        adder: The instance of `Adder` that is being tested.
        first: The first `dm_env.TimeStep` that is used to call
          `Adder.add_first()`.
        steps: A sequence of (action, timestep) tuples that are passed to
          `Adder.add()`.
        expected_items: The sequence of items that are expected to be created
          by calling the adder's `add_first()` method on `first` and `add()` on
          all of the elements in `steps`.
        signature: Signature that written items must be compatible with.
        pack_expected_items: Deprecated and not used. If true the expected items
          are given unpacked and need to be packed in a list before comparison.
        stack_sequence_fields: Whether to stack the sequence fields of the
          expected items before comparing to the observed items. Usually False
          for transition adders and True for both episode and sequence adders.
        repeat_episode_times: How many times to run an episode.
        end_behavior: How end of episode should be handled.
        item_transform: Transformation of item simulating the work done by the
          dataset pipeline on the learner in a real setup.
      """
  
      del pack_expected_items
  
      if not steps:
          raise ValueError("At least one step must be given.")
  
      has_extras = len(steps[0]) == 3
      for _ in range(repeat_episode_times):
          # Add all the data up to the final step.
          adder.add_first(first)
          for step in steps[:-1]:
              action, ts = step[0], step[1]
  
              if has_extras:
                  extras = step[2]
              else:
                  extras = ()
  
              adder.add(action, next_timestep=ts, extras=extras)
  
          # Add the final step.
          adder.add(*steps[-1])
  
      # Force run the destructor to trigger the flushing of all pending items.
      getattr(adder, "__del__", lambda: None)()
  
      # Ending the episode should close the writer. No new writer should yet have
      # been created as it is constructed lazily.
      if end_behavior is not adders.EndBehavior.CONTINUE:
          self.assertEqual(self.num_episodes(), repeat_episode_times)
  
      # Make sure our expected and observed data match.
      observed_items = self.items()
  
      # Check matching number of items.
      self.assertEqual(len(expected_items), len(observed_items))
  
      # Check items are matching according to numpy's almost_equal.
      for expected_item, observed_item in zip(
          expected_items, observed_items
      ):
          if stack_sequence_fields:
              expected_item = tree_utils.stack_sequence_fields(
                  expected_item
              )
  
          # Apply the transformation which would be done by the dataset in a real
          # setup.
          if item_transform:
              observed_item = item_transform(observed_item)
  
          tree.map_structure(
              np.testing.assert_array_almost_equal,
              tree.flatten(expected_item),
              tree.flatten(observed_item),
          )
  
      # Make sure the signature matches was is being written by Reverb.
      def _check_signature(spec: tf.TensorSpec, value: np.ndarray):
          self.assertTrue(
              spec.is_compatible_with(tf.convert_to_tensor(value))
          )
  
      # Check that it is possible to unpack observed using the signature.
      for item in observed_items:
          tree.map_structure(
              _check_signature,
              tree.flatten(signature),
              tree.flatten(item),
          )
  
imports: from typing import Any, Callable, Optional, Sequence, Tuple, TypeVar, Union
  from acme import specs
  from acme import types
  from acme.adders import base
  from acme.adders import reverb
  from acme.utils import tree_utils
  import dm_env
  import numpy
  import reverb
  import tensorflow
  import tree
  from absl.testing import absltest
label_desc: Use image node_id 7 for calling the AdderTestMixin obj's underlying member method code with example usage: obj.run_test_adder(adder, first, steps, expected_items, signature, pack_expected_items, stack_sequence_fields, repeat_episode_times, end_behavior, item_transform) without return types