code: def test_to_sample_batch(self):
      # Generate an environment and episode and sample 100 timesteps.
      episode, env = self._mock_multi_agent_records_from_env()
  
      # Now convert to sample batch.
      batch = episode.to_sample_batch()
  
      # Assert that the timestep in the `MultiAgentBatch` is identical
      # to the episode timestep.
      self.assertEqual(len(batch), len(episode))
      # Assert that all agents are present in the multi-agent batch.
      # Note, all agents have collected samples.
      for agent_id in episode._agent_ids:
          self.assertTrue(agent_id in batch.policy_batches)
      # Assert that the recorded history length is correct.
      for agent_id, agent_eps in episode.agent_episodes.items():
          self.assertEqual(len(agent_eps), len(batch[agent_id]))
      # Assert that terminated agents are terminated in the sample batch.
      for agent_id in ["agent_1", "agent_5"]:
          self.assertTrue(batch[agent_id]["terminateds"][-1])
  
      # Now test that when creating a successor its sample batch will
      # contain the correct values.
      successor = episode.cut()
      # Run 100 more timesteps for the successor.
      successor, env = self._mock_multi_agent_records_from_env(
          episode=successor, env=env, init=False
      )
      # Convert this episode to a `MultiAgentBatch`.
      batch = successor.to_sample_batch()
      # Assert that the number of timesteps match between episode and batch.
      # Note, the successor starts at `ts=100`.
      self.assertEqual(len(batch), len(successor))
      # Assert that all agents that were not done, yet, are present in the batch.
      for agent_id in env._agents_alive:
          self.assertTrue(agent_id in batch.policy_batches)
      # Ensure that the timesteps for each agent matches the it's batch length.
      for agent_id, agent_eps in successor.agent_episodes.items():
          # Note, we take over agent_ids
          if not agent_eps.is_done:
              self.assertEqual(len(agent_eps), len(batch[agent_id]))
      # Assert that now all agents are truncated b/c the environment truncated
      # them.
      for agent_id in batch.policy_batches:
          self.assertTrue(batch[agent_id]["truncateds"][-1])
  
      # Test now that when we concatenate the same logic holds.
      episode.concat_episode(successor)
      # Convert the concatenated episode to a sample batch now.
      batch = episode.to_sample_batch()
      # Assert that the length of episode and batch match.
      self.assertEqual(len(batch), len(episode))
      # Assert that all agents are present in the multi-agent batch.
      # Note, in the concatenated episode - in contrast to the successor
      # - we have all agents stepped.
      for agent_id in episode._agent_ids:
          self.assertTrue(agent_id in batch.policy_batches)
      # Assert that the recorded history length is correct.
      for agent_id, agent_eps in episode.agent_episodes.items():
          self.assertEqual(len(agent_eps), len(batch[agent_id]))
      # Assert that terminated agents are terminated in the sample batch.
      for agent_id in ["agent_1", "agent_5"]:
          self.assertTrue(batch[agent_id]["terminateds"][-1])
      # Assert that all the other agents are truncated by the environment.
      for agent_id in env._agents_alive:
          self.assertTrue(batch[agent_id]["truncateds"][-1])
  
      # Finally, test that an empty episode, gives an empty batch.
      episode = MultiAgentEpisode(agent_ids=env.get_agent_ids())
      # Convert now to sample batch.
      batch = episode.to_sample_batch()
      # Ensure that this batch is empty.
      self.assertEqual(len(batch), 0)
  
imports: import gymnasium
  import numpy
  import unittest
  from typing import List, Optional, Tuple
  import ray
  from ray.rllib.env.multi_agent_env import MultiAgentEnv
  from ray.rllib.env.multi_agent_episode import MultiAgentEpisode
  from ray.rllib.utils.typing import MultiAgentDict
label_desc: Use image node_id 11 for calling the TestMultiAgentEpisode obj's underlying member method code with example usage: obj.test_to_sample_batch() without return types