code: def test_end_to_end_update(self):
      config = BaseTestingAlgorithmConfig()
  
      for _ in framework_iterator(config, frameworks=("torch", "tf2")):
          learner = config.build_learner(env=self.ENV)
          reader = get_cartpole_dataset_reader(batch_size=512)
  
          min_loss = float("inf")
          for iter_i in range(1000):
              batch = reader.next()
              results = learner.update_from_batch(
                  batch=batch.as_multi_agent()
              )
  
          loss = results[ALL_MODULES][Learner.TOTAL_LOSS_KEY]
          min_loss = min(loss, min_loss)
          print(
              f"[iter = {iter_i}] Loss: {loss:.3f}, Min Loss: {min_loss:.3f}"
          )
          # The loss is initially around 0.69 (ln2). When it gets to around
          # 0.58 the return of the policy gets to around 100.
          if min_loss < 0.58:
              break
      self.assertLess(min_loss, 0.58)
  
imports: import gymnasium
  import numpy
  import tempfile
  import unittest
  import ray
  from ray.rllib.core.learner.learner import Learner
  from ray.rllib.core.testing.testing_learner import BaseTestingAlgorithmConfig
  from ray.rllib.policy.sample_batch import DEFAULT_POLICY_ID
  from ray.rllib.utils.numpy import convert_to_numpy
  from ray.rllib.utils.framework import try_import_tf, try_import_torch
  from ray.rllib.utils.test_utils import check, framework_iterator, get_cartpole_dataset_reader
  from ray.rllib.utils.metrics import ALL_MODULES
label_desc: Use image node_id 3 for calling the TestLearner obj's underlying member method code with example usage: obj.test_end_to_end_update() without return types