class_docstr: Test that the hooks are working correctly for plugins
code: def test_collect_report(
      self, pytester: Pytester, pytestconfig: Config
  ) -> None:
      pytester.makepyfile(
          """
              def test_a(): assert False
              def test_b(): pass
          """
      )
      reprec = pytester.inline_run()
      reports = reprec.getreports("pytest_collectreport")
      assert len(reports) == 3
      for rep in reports:
          data = pytestconfig.hook.pytest_report_to_serializable(
              config=pytestconfig, report=rep
          )
          assert data["$report_type"] == "CollectReport"
          new_rep = pytestconfig.hook.pytest_report_from_serializable(
              config=pytestconfig, data=data
          )
          assert new_rep.nodeid == rep.nodeid
          assert new_rep.when == "collect"
          assert new_rep.outcome == rep.outcome
  
imports: from typing import Sequence
  from typing import Union
  import pytest
  from _pytest._code.code import ExceptionChainRepr
  from _pytest._code.code import ExceptionRepr
  from _pytest.config import Config
  from _pytest.pytester import Pytester
  from _pytest.python_api import approx
  from _pytest.reports import CollectReport
  from _pytest.reports import TestReport
label_desc: Use image node_id 2 for calling the TestHooks obj's underlying member method code with example usage: obj.test_collect_report(pytester, pytestconfig) without return types