code: def test_evaluator_evaluate_if_necessary(
      save_best_so_far_agent, n_steps, n_episodes
  ):
      outdir = tempfile.mkdtemp()
  
      # MagicMock can mock eval_mode while Mock cannot
      agent = mock.MagicMock()
      agent.act.return_value = "action"
      agent.get_statistics.return_value = []
  
      env = mock.Mock()
      env.reset.return_value = "obs"
      env.step.return_value = ("obs", 0, True, {})
      env.get_statistics.return_value = []
  
      evaluation_hook = mock.create_autospec(
          spec=pfrl.experiments.evaluation_hooks.EvaluationHook
      )
  
      either_none = (n_steps is None) != (n_episodes is None)
      if not either_none:
          with pytest.raises(AssertionError):
              agent_evaluator = evaluator.Evaluator(
                  agent=agent,
                  env=env,
                  n_steps=n_steps,
                  n_episodes=n_episodes,
                  eval_interval=3,
                  outdir=outdir,
                  max_episode_len=None,
                  step_offset=0,
                  evaluation_hooks=[evaluation_hook],
                  save_best_so_far_agent=save_best_so_far_agent,
              )
      else:
          value = n_steps or n_episodes
          agent_evaluator = evaluator.Evaluator(
              agent=agent,
              env=env,
              n_steps=n_steps,
              n_episodes=n_episodes,
              eval_interval=3,
              outdir=outdir,
              max_episode_len=None,
              step_offset=0,
              evaluation_hooks=[evaluation_hook],
              save_best_so_far_agent=save_best_so_far_agent,
          )
  
          agent_evaluator.evaluate_if_necessary(t=1, episodes=1)
          assert agent.act.call_count == 0
          assert evaluation_hook.call_count == 0
  
          agent_evaluator.evaluate_if_necessary(t=2, episodes=2)
          assert agent.act.call_count == 0
          assert evaluation_hook.call_count == 0
  
          # First evaluation
          agent_evaluator.evaluate_if_necessary(t=3, episodes=3)
          assert agent.act.call_count == value
          assert agent.observe.call_count == value
          assert evaluation_hook.call_count == 1
          if save_best_so_far_agent:
              assert agent.save.call_count == 1
          else:
              assert agent.save.call_count == 0
  
          # Second evaluation with the same score
          agent_evaluator.evaluate_if_necessary(t=6, episodes=6)
          assert agent.act.call_count == 2 * value
          assert agent.observe.call_count == 2 * value
          assert evaluation_hook.call_count == 2
          if save_best_so_far_agent:
              assert agent.save.call_count == 1
          else:
              assert agent.save.call_count == 0
  
          # Third evaluation with a better score
          env.step.return_value = ("obs", 1, True, {})
          agent_evaluator.evaluate_if_necessary(t=9, episodes=9)
          assert agent.act.call_count == 3 * value
          assert agent.observe.call_count == 3 * value
          assert evaluation_hook.call_count == 3
          if save_best_so_far_agent:
              assert agent.save.call_count == 2
          else:
              assert agent.save.call_count == 0
  
file_path: pfrl/tests/experiments_tests/test_evaluator.py
imports: import tempfile
  import unittest
  from unittest import mock
  import numpy
  import pytest
  import pfrl
  from pfrl.experiments import evaluator
label_desc: Use image node_id 1 for calling a global function with example usage: test_evaluator_evaluate_if_necessary(save_best_so_far_agent, n_steps, n_episodes) without return types