code: def testMetronome(self):
      start_time = time.time() + 0.1
      qpm = 180
      self.midi_hub.start_metronome(start_time=start_time, qpm=qpm)
      time.sleep(0.8)
  
      self.midi_hub.stop_metronome()
      self.assertEqual(7, self.port.message_queue.qsize())
  
      msg = self.port.message_queue.get()
      self.assertEqual(msg.type, "program_change")
      next_tick_time = start_time
      while not self.port.message_queue.empty():
          msg = self.port.message_queue.get()
          if self.port.message_queue.qsize() % 2:
              self.assertEqual(msg.type, "note_on")
              self.assertAlmostEqual(
                  msg.time, next_tick_time, delta=0.01
              )
              next_tick_time += 60.0 / qpm
          else:
              self.assertEqual(msg.type, "note_off")
  
imports: import collections
  import queue
  import threading
  import time
  from magenta.common import concurrency
  from magenta.interfaces.midi import midi_hub
  import mido
  from note_seq import testing_lib
  from note_seq.protobuf import music_pb2
  import tensorflow.compat.v1
label_desc: Use image node_id 8 for calling the MidiHubTest obj's underlying member method code with example usage: obj.testMetronome() without return types