code: def check_observation_matches_spec(self, obs, obs_spec):
      self.assertCountEqual(obs_spec.keys(), obs.keys())
      for k, o in obs.items():
          if k == "map_name":
              self.assertIsInstance(o, str)
              continue
  
          descr = "%s: spec: %s != obs: %s" % (k, obs_spec[k], o.shape)
  
          if o.shape == (0,):  # Empty tensor can't have a shape.
              self.assertIn(0, obs_spec[k], descr)
          else:
              self.assertEqual(len(obs_spec[k]), len(o.shape), descr)
              for a, b in zip(obs_spec[k], o.shape):
                  if a != 0:
                      self.assertEqual(a, b, descr)
  
file_path: pysc2/pysc2/tests/obs_spec_test.py
imports: from absl.testing import absltest
  from pysc2.agents import random_agent
  from pysc2.env import sc2_env
  from pysc2.tests import utils
label_desc: Use image node_id 3 for calling the TestObservationSpec obj's underlying member method code with example usage: obj.check_observation_matches_spec(obs, obs_spec) without return types